Met*_*lis 24 javascript oop jquery
很长一段时间以来,我一直在努力使我的JavaScript更加面向对象.我也看了几个不同的实现,但我无法决定是否有必要.
我想回答的是以下问题
bob*_*nce 19
呵呵.对我来说,它看起来比它需要的要复杂得多.
实际上看起来更接近我真的对它this._super()在一个方法中提供什么以及调用超类方法所做的事情有所不同.
代码引入了依赖typeof==='function'(对于某些对象不可靠),Function#toString(argh,函数分解也不可靠),并根据您是否_super在函数体中使用了字节序列来决定是否进行换行(即使您只是在字符串中使用它.如果你尝试例如.this['_'+'super']它将失败).
如果你在函数对象上存储属性(例如MyClass.myFunction.SOME_PRIVATE_CONSTANT,你可能会保持名称空间清洁),那么换行将阻止你获得这些属性.如果在方法中抛出异常并捕获同一对象的另一个方法,_super最终会指向错误的东西.
所有这些只是为了让你的超类的同名方法更容易调用.但我不认为在JS中特别难以做到这一点.它对自己的好处太聪明了,并且在整个过程中使整体变得不那么可靠.(哦,并且arguments.callee在严格模式下无效,但这并不是他的错,因为他发布之后发生了这种情况.)
这就是我目前用于课程的内容.我并不认为这是"最好的" JS类系统,因为有负载的做它和一堆不同的功能,你可能需要添加或不加不同的方式.但它非常轻巧,旨在成为"JavaScript",如果这是一个词.(事实并非如此.)
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() {};
Run Code Online (Sandbox Code Playgroud)
它提供:
防止意外丢失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
Run Code Online (Sandbox Code Playgroud)
超类调用是通过专门命名你想要的方法来完成的call,有点像Python.如果你想避免再次命名,你可以_super在构造函数中添加一个成员Person(所以你可以说Ninja._super.prototype._init.call,或者也许Ninja._base._init.call).
JavaScript是基于原型的,而不是基于类的.我的建议是不要打它并用JS方式声明子类型:
MyDerivedObj.prototype = new MySuperObj();
MyDerivedObj.prototype.constructor = MyDerivedObj;
Run Code Online (Sandbox Code Playgroud)
看看在没有使用继承的情况下你能走多远.将其视为一种性能破解(在不需要真正必要的地方),而不是设计原则.
在像JS这样的高度动态的语言中,很少需要知道对象是否是一个 Person.您只需要知道它是否具有 firstName属性或eatFood方法.您通常不需要知道对象是否是数组; 如果它有一个length属性和一些以整数命名的其他属性,那通常就足够了(例如Arguments对象)."如果它像鸭子一样走路,像鸭子一样嘎嘎叫,那就是鸭子."
// give back a duck
return {
walk: function() { ... },
quack: function() { ... }
};
Run Code Online (Sandbox Code Playgroud)
是的,如果您正在制作大量小对象,每个小对象都有几十种方法,那么通过各种方法将这些方法分配给原型,以避免在每个实例中创建数十个插槽的开销.但将其视为减少内存开销的一种方式 - 仅仅是优化.通过隐藏你对new某种工厂功能的使用来帮助你的用户,所以他们甚至不需要知道如何创建对象.他们只需要知道它有方法foo或属性bar.
(并且请注意,在这种情况下,您不会真正建模经典继承.它仅仅相当于定义单个类以获得共享vtable的效率.)