Немного магический способ наследования
Не люблю использовать всякие обертки, типа
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 ); // ... много кода } Хотя еще не представляю, как добиться этого. В этой теме http://javascript.ru/forum/misc/3127...nstructor.html было выяснено, что prototype нельзя переопределить после инициализации экземпляра конструктора. |
Очень топорный вариант:
var inherit = function( object, Child, Parent ) { var args = Array.prototype.slice.call( arguments, 3 ); Parent.apply( object, args ); extendPrototype( Child.prototype, Parent.prototype ); } var extendPrototype = function( o1, o2 ) { for( var i in o2 ) { o1[i] = o1[i] || o2[i]; } }; var Constructor = function() { inherit( this, Constructor, Parent ) } Здесь не будет работать instanceof. |
Цитата:
имя_экзэмпляра.метод а через имя_экзэмпляра.constructor.prtototype.method |
Цитата:
В общем, проведя двое суток над этой задачей, так и не нашел решения. Придется использовать старый дедовский способ наследования, определенного после прототипа. За то можно наследовать сразу несколько конструкторов, так как это неотъемлемая особенность прототипного программирования. Function.prototype.extendNotEnum( 'inherits', function( Parent ) { var prototype = this.prototype; this.prototype = Object.create( Parent.prototype ); this.prototype.constructor = this; this.prototype.extend( prototype ); }); // методы extend и extendNotEnum — кастомные. Первый добавляет новые свойства в контекст, второй делает то же самое, но с enumerable: false Child = function(){ Parent.apply( this, arguments ) } Child.prototype = {} Child.inherits( Parent ); |
Часовой пояс GMT +3, время: 21:48. |