John Resig的OO JavaScript实现生产安全吗?

Met*_*lis 24 javascript oop jquery

很长一段时间以来,我一直在努力使我的JavaScript更加面向对象.我也看了几个不同的实现,但我无法决定是否有必要.

我想回答的是以下问题

  • 约翰Resig的简单继承结构使用安全生产?
  • 有什么办法可以说明它的测试情况如何?
  • 除了Joose,我还有其他选择吗?我需要一个易于使用,快速且稳健的产品.它还需要与jQuery兼容.

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)

它提供:

  1. 防止意外丢失new.另一种方法是默默地重定向X()new X()如此缺失的new作品.这是一个最好的折腾; 我去了显式错误,以便一个人不习惯写作而不会new导致其他未定义的对象出现问题.无论哪种方式都比不可接受的JS默认this.属性让属性落入window并且以后神秘地出错.

  2. 一个可继承的_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).


Chr*_*unt 5

JavaScript是基于原型的,而不是基于类的.我的建议是不要打它并用JS方式声明子类型:

MyDerivedObj.prototype = new MySuperObj();
MyDerivedObj.prototype.constructor = MyDerivedObj;
Run Code Online (Sandbox Code Playgroud)

  • 这个问题是调用`new MySuperObj()`调用`MySuperObj()`的构造函数中的初始化代码,就好像你实际实例化了一个`MySuperObj`.一旦你在构造函数中有任何不重要的东西,这就不行了,因为你需要在构造一个`MyDerivedObj`实例时调用`MySuperObj`初始化代码,而不是在define-time. (3认同)

Dan*_*ker 5

看看在没有使用继承的情况下你能走多远.将其视为一种性能破解(在不需要真正必要的地方),而不是设计原则.

在像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的效率.)