Ответ 1
Только вызов Base.apply(...)
не устанавливает наследование. Все, что .apply
делает, устанавливает this
в первый аргумент, ничего больше. Важно вызвать родительский конструктор, но этого недостаточно.
Что вам нужно сделать, так это правильно настроить цепочку прототипов. То есть вам нужно установить Derivation1.prototype
на то, что наследуется от Base.prototype
.
Поскольку каждый экземпляр функции-конструктора наследуется от прототипа функций конструктора, вы увидите код, например
Derivation1.prototype = new Base();
Это плохая идея, и вы уже можете понять, почему: Base
ожидает аргументов для настройки специальных свойств экземпляра (name
в этом случае). Но мы не заботимся об этих свойствах, так как мы инициализируем их позже в дочернем конструкторе с Base.apply(this, ...)
.
Итак, все, что нам нужно - это объект, наследующий от Base.prototype
, и, к счастью, ECMASCript 5 определяет функцию, которая может сделать это для нас (polyfill):
Derivation1.prototype = Object.create(Base.prototype);
Это создает новый объект, наследующий от Base.prototype
. Теперь, поскольку вы заменили оригинальный прототип новым объектом, вы должны установить свойство constructor
так, чтобы оно правильно указывало на Derivation1
:
Derivation1.prototype.constructor = Derivation1;
Ниже приведен полный пример. Также посмотрите эту скрипку и этот отличный ответ T.J. Crowder, который объясняет в основном те же проблемы, но, возможно, лучше.
Пример:
function BaseObject(name){
this.name = name;
}
// move properties shared by all instances to the prototype!
BaseObject.prototype.sayWhoAmI = function() {
console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1));
console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2));
console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject));
};
function Derivation1(){
BaseObject.apply(this, ['first derivation']);
}
Derivation1.prototype = Object.create(BaseObject.prototype);
Derivation1.prototype.constructor = Derivation1;
// some useless method of the child "class"
Derivation1.prototype.someOtherMethod = function() {
return 42;
};
var first = new Derivation1();
first.sayWhoAmI();