2014-12-16 3 views
1

Рассмотрим эти две версии построения иерархии объектов в JavaScript:Prototype: Разница между этими двумя сценариями

Версия 1

function Employee() { 
    this.name = "NoName"; 
    this.dept = "NoDept"; 
}; 

function Manager() { 
    Employee.call(this); 
    this.reports = "Nobody"; 
} 

//Manager.prototype = Object.create(Employee.prototype); 
var m = new Manager(); 
console.log(m.name); 

Версия 2

function Employee() { 
    this.name = "NoName"; 
    this.dept = "NoDept"; 
}; 

function Manager() { 
    //Employee.call(this); 
    this.reports = "Nobody"; 
} 

Manager.prototype = Object.create(Employee.prototype); 
var m = new Manager(); 
console.log(m.name); 

В первом версия, свойство name доступно, хотя мы не используем p наследование ротипота (конечно, из-за метода call()). Во второй версии мы комментируем call() и определяем цепочку прототипов, и все же свойство name недоступно.

Это оставляет меня интересно, почему, зачем беспокоиться о Manager.prototype?

ответ

2

Обратите внимание, что в конструкторе:

function Employee() { 
    this.name = "NoName"; 
    this.dept = "NoDept"; 
} 

когда называют:

new Employee(); 

имя и свойства добавляются непосредственно к новому объекту, назначенного этогоотдела. Они не наследуются, они находятся непосредственно на экземпляре.

В первой версии, свойство имя доступно, даже если мы не используем наследование прототипа

Потому что, когда вы делаете:

Employee.call(this); 

вы добавляете имя имущество непосредственно к экземпляру Менеджер. Он не унаследован, он находится непосредственно на экземпляре.

Во втором варианте мы закомментировать вызов() и определить цепочку прототипов, и в то же свойство имя недоступно

Поскольку имя свойство не на цепочке прототипов , то Сотрудник конструктор помещает его непосредственно на это (который, как правило, быть экземпляром Работника но из-за того, как вы это называете из менеджера, это экземпляр от Менеджер).

Это оставляет мне интересно, почему, зачем беспокоиться о Manager.prototype?

Так что экземпляры менеджера унаследует от Employee.prototype.Но вы не добавили никаких методов в Employee.prototype, так что наследовать нечего.

+0

Очень хороший ответ! Я думал, что Employee.call (это) имитирует вызов супер() классических объектно-ориентированных языков; следовательно, путаница. Ваш ответ был прозрением! :) – dotslash

1

Зачем беспокоиться Manager.prototype в сочетании с object.create. потому что, если вы не используете это, он не наследует прототипы методов вашего базового/суперкласса «Сотрудник». Обычно в реальном сценарии ваш суперкласс будет иметь прототипы, которые вы хотите наследовать, и в этом сценарии object.create дает вам более простой способ достичь этого.
Рассмотрим ниже пример

function Employee() { 
    this.name = "NoName"; 
    this.dept = "NoDept"; 
}; 
Employee.prototype.method1 = function(){//super class method 
alert("super method"); 
} 

function Manager() { 
    Employee.call(this);//inherit direct properties 
    this.reports = "Nobody"; 
} 

Manager.prototype = Object.create(Employee.prototype);//inherit prototype 
var m = new Manager(); 
m.method1();//commenting out object.create will not allow this access 
+0

Я получаю его, но зачем идти на все проблемы с добавлением 'method1()' в 'Employee.prototype'? Я могу просто добавить его в «Employee» и сделать его доступным для всех объектов «Manager». – dotslash

+0

@ dotslash рассмотрите ситуацию, когда вам нужно создать несколько экземпляров Employee/Manager. В этом случае вы не хотите иметь отдельную копию этих методов для каждого экземпляра, поскольку эти методы не являются состоянием экземпляра типа name, dept. Прототип используется всем экземпляром и не копируется отдельно для каждого экземпляра. – Amitesh

+0

Ницца! Большое спасибо за объяснение. :) – dotslash

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