2013-04-05 2 views
6

Я изучаю понятие наследования в JavaScript, и учебник я смотрю на использует этот код:Наследование в JavaScript,

// define the Student class 
function Student() { 
    // Call the parent constructor 
    Person.call(this); 
} 

// inherit Person 
Student.prototype = new Person(); 

// correct the constructor pointer because it points to Person 
Student.prototype.constructor = Student; 

Мой вопрос, почему это необходимо как вызвать родительский конструктор , Person.call(this) и установить прототип Student, равный новому объекту Person (т.е. Student.prototype = new Person();)?

+0

http://stackoverflow.com/questions/892595/javascript-prototypal-inheritance?rq=1 –

ответ

5

Есть два отдельных вопроса, с которыми нужно иметь дело.

Первый должен убедиться, что новые объекты Student наследуют от Person объектов. Вот почему вы делаете Student.prototype = new Person(). Это делает Student.prototype a Person, так что объекты Student наследуют все, что наследует этот объект. (от Person.prototype).

Второй способ - применить любое поведение в конструкторе Person к любым новым объектам Student. Вот почему вы делаете Person.call(this). Это технически не требуется, если конструктор Person не имеет никакого кода, который изменяет новый объект, но это все же хорошая идея сделать это на всякий случай, если вы добавите некоторый код в Person позже.


Примечание стороны, при настройке наследования, это лучше сделать:

Student.prototype = Object.create(Person.prototype) 

... и подкладку Object.create в случае необходимости. Таким образом, вам действительно не нужно вызывать конструктор Person, чтобы получить новый объект, который наследуется от Person.prototype. Опять же, иногда это не проблема, но иногда возникают побочные эффекты в конструкторе, которые нежелательны при настройке наследования.

+0

Мне просто интересно ... в чем причина установки конструктора прототипа? 'Student.prototype.constructor = Student;' – Polaris878

+2

+1 Для исправления, удаляющего 'new Person()', что может быть проблематичным, если родительский конструктор имеет параметры. Также внутри конструктора можно было бы также отправлять аргументы. –

+1

@ Polaris878: Это связано с тем, что объект 'Student.prototype' по умолчанию имеет свойство' .constructor', которое указывает на функцию 'Student' ... но этот объект заменяется, поэтому, если требуется свойство' .constructor', его необходимо добавить вручную к новому объекту. – 2013-04-05 21:31:28

0

После выполнения некоторых испытаний, на мой взгляд, прототип объекта и объявления свойств, сделанные в его определяющей функции, являются отдельными. Однако при создании нового объекта конструктор будет извлекать свойства как из определяющей функции, так и из прототипа создаваемого объекта.

Например,

function Person() 
{ 

    this.name = "james"; 
    this.age = "shfifty-five"; 


} 

console.log(Person.prototype.name); // prints "undefined", showing how declaring function Person() and Person.prototype are separate. 

Person.prototype.gender = "male"; 

var human = new Person(); 

console.log(human.name); // prints "james", showing how the object took properties from declaring function Person(). 
console.log(human.gender); // prints "male", showing how the object took properties from object prototype Person.prototype. 


function Student() 
{ 

    this.gpa = 4.00; 


} 



Student.prototype = new Person(); 

Student.prototype.constructor = Student; 


var myStudent = new Student(); 

console.log(myStudent.name); // prints "james" 
console.log(myStudent.gender); // prints "male" 
/*from above two lines, inheritance holds even though 1) Person() defining function was not called inside Student() defining function 
and 2) Person() defining function declares properties of Person object.*/ 
console.log(myStudent.gpa); // prints "4" 

Как вы можете видеть, в этом случае функция определения лица делает изменяет свойства своего объекта. Но по-прежнему не нужно вызывать функцию Person внутри конструктора Student, потому что конструктор new Person() будет извлекать свойства из Person.prototype и функции определения function Person().

+1

Это зависит ... Каждый новый объект 'Student' наследует свойства объекта' Student.prototype'. В вашем примере, когда вы выполняете 'Student.prototype = new Person()', к объекту 'Person' добавляются некоторые свойства, поэтому, естественно, они будут унаследованы. Но что, если значения, назначенные в конструкторе 'Person', не являются статическими? Если вы не вызываете «Личность» на новых объектах «Студент», они всегда будут ссылаться на те же значения свойств, которые установлены на объекте прототипа. Если вы * * хотели, чтобы статические значения были унаследованы, вы должны поместить их в 'Person.prototype'. – 2013-04-06 19:11:00

Смежные вопросы