Я пытаюсь понять наследование на основе прототипов в JavaScript. Для того, чтобы создать цепочку прототипов с функциями конструктора, вы обычно делаете это таким образом:Тип наследования: Почему вам нужно создать новый объект, вместо того, чтобы напрямую устанавливать прототип?
function Person(name, gender){
this.name = name;
this.gender = gender;
}
function Male(name){
Person.call(this, name, "male");
}
Male.prototype = Object.create(Person.prototype);
Object.defineProperty(Male.prototype, "constructor", {
enumerable: false, value: Male, writeable: true
});
var person1 = new Male("Chris");
Так, Male.prototype
создать совершенно новый объект, который имеет внутренний [[Prototype]] набор свойств для родительского объекта. Поскольку это новый объект, вам все равно нужно добавить неперечислимое свойство constructor
.
Поскольку существует способ установить [[prototype]]
свойство непосредственно, интересно, почему вы не можете сделать это:
function Person(name, gender){
this.name = name;
this.gender = gender;
}
function Male(name){
Person.call(this, name, "male");
}
Object.setPrototypeOf(Male.prototype, Person.prototype);
var person1 = new Male("Chris");
С помощью этого решения вы просто установите [[prototype]]
свойство Male.prototype
для родительского объекта. (До ES6 вы могли использовать свойство __proto__
для установки прототипа.) Вам не нужно создавать новый объект (поскольку, насколько я знаю, js runtime автоматически прикрепляет новый объект prototype
к каждой функции), и вы не нужно явно создавать свойство constructor
, потому что оно уже существует.
Мой вопрос: почему никто не использует этот подход для установки цепи прототипов? В чем проблема?
FYI, ваша версия 'Object.create' может быть сделана немного более чисто, используя второй аргумент для определения свойства' constructor'. –
Линия 'Object.defineProperty..' на самом деле не является общим способом создания конструктора. Вся эта инструкция (эти 3 строки) просто будет: 'Male.prototype.constructor = Person;' –
@ScottMarcus: Это делает ее перечислимой. Использование 'defineProperty' позволяет вам установить правильный дескриптор свойства. –