Недавно мне понадобилось реализовать наследование в JavaScript с возможностью вызова супер конструктора ( конструктор родительского класса, кто не в курсе ). Под рукой у меня была старая добрая крокфордовская функция, которая всегда мне помогала:
Добавляем в прототип дочернего обьекта функцию _super:
UPD: Если я правильно понял эт заметку caller - MDN - Mozilla Developer Network то свойство caller не должно существовать... но тем не менее у меня все заработало.
function extend(Child, Parent){
var F = function(){}
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
Немного почесав репу я решил добавить в нее немного функционала. Идея достаточно проста -- в каждой функции в JS есть переменная arguments, которая помимо аргументов вызова функции хранит в себе свойство callee, а то в свою очередь свойство caller, которое указывает на функцию, которая вызвала текущую функцию.... Короче говоря вот что у меня получилось:function extend(Child, Parent){
var F = function(){}
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.prototype._super = function(){
if( arguments.callee.caller === Child){
Parent.apply(this, arguments);
return;
}
if( !this.__proto__){this.__proto__ = this.constructor.prototype;}
for(var o in this.__proto__){
if(this.__proto__[o] === arguments.callee.caller){
Parent.prototype[o].apply(this, arguments);
}
}
}
}
Теперь постараюсь объяснить свой ход мысли.Добавляем в прототип дочернего обьекта функцию _super:
Child.prototype._super = function(){
Первым делом эта функция проверяет не в конструкторе ли она была вызвана: if( arguments.callee.caller === Child){
И если она была вызвана в конструкторе, то мы соответственно вызываем конструктор родительского класса.Parent.apply(this, arguments);В ИЕ не существует переменной __proto__, по этому мы ее добавляем сами
if( !this.__proto__){this.__proto__ = this.constructor.prototype;}
Если функция была вызвана не из конструктора, то мы пробегаемся по всем полям в прототипе нашей текущей функции, чтоб выяснить ее имя, после чего вызываем эту самую функцию, но из родительского класса for(var o in this.__proto__){
if(this.__proto__[o] === arguments.callee.caller){
Parent.prototype[o].apply(this, arguments);
}
}
UPD: Если я правильно понял эт заметку caller - MDN - Mozilla Developer Network то свойство caller не должно существовать... но тем не менее у меня все заработало.