Ответ 1
Да. Это выглядит намного сложнее, чем мне нужно.
На самом деле, более внимательно, я действительно делаю исключение из того, что он делает, предоставляя this._super()
в то время как метод, чтобы вызвать метод суперкласса.
Код вводит зависимость от typeof==='function'
(ненадежный для некоторых объектов), Function#toString
(argh, декомпозиция функции также ненадежна) и решая, следует ли обертывать, основываясь на том, использовалась ли вы последовательность байтов _super
в теле функции (даже если вы использовали его только в строке, и если вы попробуете, например. this['_'+'super']
, это не удастся).
И если вы сохраняете свойства в своих объектах функций (например, MyClass.myFunction.SOME_PRIVATE_CONSTANT
, которые вы можете сделать, чтобы сохранить пространства имен чистыми), обертка остановит вас от получения этих свойств. И если исключение выбрано в методе и поймано в другом методе того же объекта, _super
в конечном итоге укажет на неправильную вещь.
Все это просто для того, чтобы упростить вызов своего суперклассного метода. Но я не думаю, что это особенно сложно сделать в JS. Он слишком умен для своего же блага и в процессе делает его менее надежным. (Ох и arguments.callee
недействительны в строгом режиме, хотя это и не его вина, поскольку это произошло после того, как он опубликовал его.)
Вот то, что я использую для классов на данный момент. Я не утверждаю, что это "лучшая" система класса JS, потому что есть множество различных способов сделать это и множество различных функций, которые вы можете добавить или не добавить. Но он очень легкий и нацелен на то, чтобы быть JavaScriptic, если это слово. (Это не так.)
Function.prototype.makeSubclass= function() {
function Class() {
if (!(this instanceof Class))
throw 'Constructor function requires new operator';
if ('_init' in this)
this._init.apply(this, arguments);
}
if (this!==Object) {
Function.prototype.makeSubclass.nonconstructor.prototype= this.prototype;
Class.prototype= new Function.prototype.makeSubclass.nonconstructor();
}
return Class;
};
Function.prototype.makeSubclass.nonconstructor= function() {};
Он обеспечивает:
-
защита от случайного отсутствия
new
. Альтернативой является тихое перенаправлениеX()
наnew X()
, поэтому отсутствуетnew
. Это лучший результат; Я пошел на явную ошибку, так что вы не привыкли писать безnew
и вызывают проблемы с другими объектами, не определенными так. В любом случае лучше, чем неприемлемое значение JS, позволяющее свойствамthis.
выпадать наwindow
и таинственным образом будет ошибочным позже. -
наследуемый метод
_init
, поэтому вам не нужно писать конструктор-функцию, которая ничего не делает, кроме вызова функции конструктора суперкласса.
и это действительно все.
Здесь вы можете использовать его для реализации примера Resig:
var Person= Object.makeSubclass();
Person.prototype._init= function(isDancing) {
this.dancing= isDancing;
};
Person.prototype.dance= function() {
return this.dancing;
};
var Ninja = Person.makeSubclass();
Ninja.prototype._init= function() {
Person.prototype._init.call(this, false);
};
Ninja.prototype.swingSword= function() {
return true;
};
var p= new Person(true);
p.dance(); // => true
var n = new Ninja();
n.dance(); // => false
n.swingSword(); // => true
// Should all be true
p instanceof Person &&
n instanceof Ninja && n instanceof Person
Вызов суперкласса выполняется путем конкретного наименования метода, который вы хотите, и call
ing, немного похожего на Python. Вы могли бы добавить элемент _super
к функции конструктора, если хотите избежать повторного именования Person
(так что вы скажете Ninja._super.prototype._init.call
или, возможно, Ninja._base._init.call
).