Не люблю использовать всякие обертки, типа
Constr = Constructor( Parent, function() {});
Не нравится и то, что во многих реализациях наследования, функция, отвечающая за него пишется под конструктором:
Constr = function() {
// ...много кода
}
inherit( Constr, Parent );
Из-за этого приходится скроллить вниз, дабы посмотреть, наследует ли конструктор свойства другого конструктора.
Хотелось бы использовать обычные, традиционные функции-конструкторы, но с кратким и очевидным наследованием, определенным в начале функции:
Constr = function() {
inherit( this, Parent );
// ... много кода
}
Мне кажется это красивым и удобным (а используя defineProperty можно добиться еще большей лаконичности и писать this.inherit( Parent )).
Немного магии:
var inherit = function( object, Parent ) {
var args = Array.prototype.slice.call( arguments, 2 ),
proto = object.__proto__;
Parent.apply( object, args );
if( proto.__proto__.constructor !== Parent ) {
proto.__proto__ = applyConstruct( Parent, args );
}
}
var applyConstruct = function( Constructor, args ) {
var argNames = [];
for( var i = 0; i < args.length; i++ ) {
argNames.push( 'arg' + i );
}
argNames.join( ',' );
return new Function( argNames, 'return new this( ' + argNames + ' );' ).apply( Constructor, args );
}
C1 = function C1() {
this.a = 1;
this.b = 12;
};
C1.prototype = {
m1: function() {
// 11
},
m2: function() {
// 12
}
};
C2 = function C2() {
inherit( this, C1 );
this.b = 22;
this.c = 23;
};
C2.prototype = {
m2: function() {
// 22
},
m3: function() {
// 23
}
};
C3 = function C3() {
inherit( this, C2 );
this.c = 33;
this.d = 4;
};
C3.prototype = {
m3: function() {
// 33
},
m4: function() {
// 34
}
};
Здесь используется свойство __proto__, которое не поддерживается даже новыми ИЕ. В дальнейшем постараюсь избавиться от этого свойства, но появится небольшая избыточность:
Constr = function() {
inherit( this, Constr, Parent );
// ... много кода
}
Хотя еще не представляю, как добиться этого. В этой теме
Почему не работает код? Вопрос о this.constructor. было выяснено, что prototype нельзя переопределить после инициализации экземпляра конструктора.