ОК, уловка с воспроизведением системы класса / экземпляра в JavaScript состоит в том, что вы можете использовать наследование прототипа только в экземплярах. Таким образом, вы должны иметь возможность создавать экземпляр «неэкземпляра», который используется только для наследования, и иметь метод инициализатора, отдельный от самой функции конструктора.
Это минимальная система, которую я использую (перед добавлением оборок), передавая специальное одноразовое значение в конструктор, чтобы он создавал объект без его инициализации:
Function.prototype.subclass= function() {
var c= new Function(
'if (!(this instanceof arguments.callee)) throw(\'Constructor called without "new"\'); '+
'if (arguments[0]!==Function.prototype.subclass._FLAG && this._init) this._init.apply(this, arguments); '
);
if (this!==Object)
c.prototype= new this(Function.prototype.subclass._FLAG);
return c;
};
Function.prototype.subclass._FLAG= {};
Использование new Function()
- это способ избежать образования ненужного замыкания над подклассом (). Вы можете заменить его более красивым выражением function() {...}
, если хотите.
Использование сравнительно чисто, и, как правило, похоже на объекты в стиле Python только с немного неуклюжим синтаксисом:
var Shape= Object.subclass();
Shape.prototype._init= function(x, y) {
this.x= x;
this.y= y;
};
Shape.prototype.draw= function() {
throw new Error("Arbitrary shapes cannot be drawn");
};
var Square= Shape.subclass();
Square.prototype._init= function(x, y, side) {
Shape.prototype._init.call(this, x, y);
this.side= side;
};
Square.prototype.draw= function() {
gotoXY(this.x, this.y);
lineTo(this.x+this.side, this.y); // ...
};
Обезвреживание патчей для встроенной функции (функции) немного сомнительно, но делает ее приятной для чтения, и никто не захочет for...in
над функцией.