Прототипное наследование в JavaScript
-
23-08-2019 - |
Вопрос
Я смотрел выступления Дугласа Крокфорда в театре YUI, и у меня возник вопрос о наследовании JavaScript...
Дуглас приводит этот пример, чтобы показать, что "Hoozit" наследует от "Gizmo".:
function Hoozit(id) {
this.id = id;
}
Hoozit.prototype = new Gizmo();
Hoozit.prototype.test = function (id) {
return this.id === id;
};
Почему он пишет Hoozit.prototype = new Gizmo()
вместо того , чтобы Hoozit.prototype = Gizmo.prototype
?
Есть ли какая-то разница между этими двумя?
Решение
Причина в том, что использование Hoozit.prototype = Gizmo.prototype
это означало бы, что изменение объекта-прототипа Hoozit также привело бы к изменению объектов типа Gizmo, что не является ожидаемым поведением.
Hoozit.prototype = new Gizmo()
наследуется от Gizmo, а затем оставляет Gizmo в покое.
Другие советы
Другие ответы касаются этого, но если вы ДЕЙСТВИТЕЛЬНО хотите унаследовать прототип, вы можете использовать некоторую паразитную магию:
Object.prototype.inherit = function(p) {
NewObj = function(){};
NewObj.prototype = p;
return new NewObj();
};
// Paraphrasing of Nicholas Zakas's Prototype Inheritance helper
function inheritPrototype(subType, superType) {
var prototype = Object.inherit(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
};
Теперь вы можете заменить:
Hoozit.prototype = new Gizmo();
с
inheritPrototype(Hoozit, Gizmo);
Возможно, это не стоит таких хлопот, если у вас нет действительно большого конструктора Gizmo (единственный выигрыш в моем предложении заключается в том, что вам не нужно вызывать конструктор Gizmo для подключения прототипа).У меня есть примеры многих из этих типов паттернов в Примеры TDD JavaScript.
Если он напишет Hoozit.prototype = Gizmo.prototype, любая модификация, которую он внесет позже в прототип Hoozit, будет отражена в прототипе Gizmo.
В дополнение к ответу Триптиха:Экземпляры Hoozit также унаследуют все свойства экземпляра Gizmo, а не только те, которые определены в прототипе;например:
function Gizmo() {
this.foo = 'bar'; // foo is visible in every Hoozit instance
}