嗯。对我来说,它看起来比实际需要的复杂得多。
实际上,仔细观察,我真的对在方法中提供this._super() 来调用超类方法的做法表示异议。
代码引入了对typeof==='function'(对某些对象不可靠)、Function#toString(啊,函数分解也是不可靠的)的依赖,并根据你是否使用过字节序列来决定是否换行@987654325 @ 在函数体中(即使你只在字符串中使用过它。如果你尝试例如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 的情况下进行写作,并导致其他未这样定义的对象出现问题。无论哪种方式都比让this. 属性落在window 上并在以后神秘地出错的不可接受的JS 默认值要好。
一个可继承的_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
超类调用是通过专门命名您想要的方法并calling 来完成的,有点像在 Python 中。如果您想避免再次命名Person(所以您会说Ninja._super.prototype._init.call,或者可能是Ninja._base._init.call),您可以将_super 成员添加到构造函数。