2013-02-23 7 views
7

Я изучаю некоторые аспекты объектно-ориентированного Javascript. Я наткнулся на этот фрагментНаследование Javascript: вызов Object.create при настройке прототипа

var Person = function(firstName, lastName) 
{ 
    this.lastName = lastName; 
    this.firstName = firstName; 
}; 

Object.defineProperties(Person.prototype, { 
    sayHi: { 
    value: function() { 
     return "Hi my name is " + this.firstName; 
    } 
    }, 
    fullName: { 
    get: function() { 
     return this.firstName + " " + this.lastName; 
    } 
    } 
}); 

var Employee = function(firstName, lastName, position) { 
    Person.call(this, firstName, lastName); 
    this.position = position; 
}; 

Employee.prototype = Object.create(Person.prototype); 

var john = new Employee("John", "Doe", "Dev"); 

И мой вопрос: почему этот фрагмент используют Object.create (Person.prototype)? Не следует ли нам просто перезагрузить прототип с помощью:

Employee.prototype = Person.prototype; 
+2

Большой [ответ] (http://stackoverflow.com/questions/15040955/javascript-oop-and-prototypes-with-multiple-level-inheritance?answertab=active# tab-top) к этому с сегодняшнего дня. – marekful

+0

wow. Спасибо за это. закладок для учебы! :-) –

+0

[Нет] (http://stackoverflow.com/q/12500637/1048572) – Bergi

ответ

9

Doing Employee.prototype = Person.prototype, как говорят "Сотрудник Person", а не "Сотрудник является Личностью." Любые изменения в любом прототипе будут отражены в и классах.

Вот demonstration. Очевидно, мы не хотим, чтобы наши люди работали, потому что у них нет позиции.

Так правильно настроить прототип цепи без Object.create является:

Employee.prototype = new Person; 

Но это требует создания экземпляра объекта, который является немного напуганным - особенно, если вы не хотите, конструктор человека к называться. Все экземпляры Employee собираются наследовать неопределенные свойства «firstName» и «lastName», независимо от того, хотите ли вы этого.

В этом случае это не имеет большого значения - конструктор Employee собирается установить те свойства на себе, которые будут заменять свойства, унаследованные от Person. Но рассмотрим this example. Можно подумать, что freeTime - это свойство уровня экземпляра для Person, которое не будет скопировано, потому что оно не на прототипе. Кроме того, мы никогда не вызывали конструктор Person из Employee. Не так - freeTime был установлен на прототипе Employee, потому что нам нужно было создать экземпляр объекта.

Таким образом, лучшее и самое чистое наследование, которое вы можете сделать, - через Object.create. Если вы хотите вызвать конструктор родительского класса, вы можете сделать это явно из конструктора подкласса. Еще одна приятная вещь: Object.create имеет второй (необязательный) аргумент defineProperties. Таким образом, вы можете также сделать это:

Employee.prototype = Object.create(Person.prototype, { 
    work: { 
    value: function() { 
     return this.fullName+" is doing some "+this.position+" stuff"); 
    } 
    } 
}); 

Конечно, если вы должны поддерживать устаревшие версии браузеров, вы не можете использовать Object.create. Альтернативой является использование клона/расширение из библиотек, таких как underscore или lodash. Или есть этот маленький танец:

var subclass = function() { }; 
subclass.prototype = Person.prototype; 
Employee.prototype = new subclass; 
+0

Почему это правильный путь? Я имею в виду, что, если объект Person имеет свойства/поля (firstName, lastName)? Должен ли прототип сотрудника иметь к нему доступ? А также мне нужно предоставить lastName & firstName, потому что им нужна функция конструктора. – dragonfly

+0

Обновлено с демонстрацией. –

+0

Я думаю, что приведенный здесь пример плохой. Я * хотел бы ожидать, что 'freeTime' будет скопирован в дочерний объект, потому что он установлен в конструкторе родителя, и вы должны вызвать этот конструктор из конструктора дочернего элемента. – Jez

1

Я предполагаю, что целью является создание нового объекта, а не просто ссылки от Person.

//create a new object with its prototype assigned to Person.prototype 
Employee.prototype = Object.create(Person.prototype);