首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >John的OO JavaScript实现生产安全吗?

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

Stack Overflow用户
提问于 2010-09-28 22:14:27
回答 3查看 2.2K关注 0票数 24

很长一段时间以来,我一直在兜售使我的JavaScript更面向对象的想法。我也看过几个不同的实现,但我只是不能决定它是否必要。

我想回答的是以下问题

  • 约翰·雷西格简单的继承结构用于生产是否安全?
  • 有没有办法知道它测试得有多好?
  • 除了乔斯,我还有其他的选择吗?我需要一个是容易使用,快速和健壮的。它还需要与jQuery兼容。
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-09-28 22:45:08

哈。在我看来,它看起来比需要的复杂得多。

实际上,更仔细地看,我真的反对它在方法中提供this._super()的做法,即调用超类方法。

代码引入了对typeof==='function' (某些对象不可靠)、Function#toString (argh,函数分解也不可靠)的依赖,并根据是否在函数体中使用了字节_super序列来决定是否包装(即使您只在字符串中使用过它)。如果你试一试。this['_'+'super'],它会失败的)。

如果要在函数对象上存储属性(例如MyClass.myFunction.SOME_PRIVATE_CONSTANT,这可能是为了保持名称空间的清洁),则包装将阻止您获取这些属性。如果在方法中抛出异常,并在同一对象的另一个方法中捕获异常,_super将最终指向错误的东西。

所有这些只是为了让调用超类的同名方法变得更容易。但我不认为这在JS中特别难做。这对自己来说太聪明了,而且在这个过程中使整个过程变得不那么可靠。(哦,而且arguments.callee在严格模式下是无效的,尽管这并不是他的错,因为这是在他发布后发生的。)

这是我现在用来上课的东西。我并不认为这是“最好”的JS类系统,因为有很多不同的方法可以实现,还有很多不同的特性需要添加或不添加。但是它非常轻量级,它的目标是成为‘JavaScriptic’,如果这是一个词的话。(事实并非如此。)

代码语言: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() {};

它规定:

  1. 防止意外失踪的new。另一种方法是静默地将X()重定向到new X(),这样缺少的new就能工作。这是一个最好的选择;我选择了显式错误,这样一个人就不会习惯在没有new的情况下写作,并在其他没有这样定义的对象上造成问题。这两种方法都比不能接受的JS默认设置要好,即让this.属性落入window,然后神秘地出错。
  2. 一个可继承的_init方法,因此您不必编写只调用超类构造函数的构造函数。

仅此而已。

下面是如何使用它实现Resig的示例:

代码语言:javascript
复制
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来完成的,有点像在Python中那样。如果您想避免再次命名_super,可以向构造函数添加一个Person成员(所以您可以说是Ninja._super.prototype._init.call,或者是Ninja._base._init.call)。

票数 19
EN

Stack Overflow用户

发布于 2010-09-29 04:35:02

JavaScript是基于原型的而不是基于类的。我的建议是不要用JS方式声明子类型:

代码语言:javascript
复制
MyDerivedObj.prototype = new MySuperObj();
MyDerivedObj.prototype.constructor = MyDerivedObj;
票数 5
EN

Stack Overflow用户

发布于 2010-09-29 09:20:11

看看在不使用继承的情况下可以走多远。将其视为一种性能攻击(在真正需要的地方勉强应用),而不是一种设计原则。

在像JS这样的高度动态的语言中,很少有必要知道对象是否是Person。您只需要知道它是否具有firstName属性或eatFood方法。您通常不需要知道一个对象是否是一个数组;如果它有一个length属性和一些以整数命名的其他属性,那通常就足够好了(例如,参数对象)。“如果它像鸭子一样走路,像鸭子一样嘎嘎叫,那就是鸭子。”

代码语言:javascript
复制
// give back a duck
return { 
  walk: function() { ... }, 
  quack: function() { ... } 
};

是的,如果您正在制造大量的小对象,每个对象都有几十个方法,那么无论如何都要将这些方法分配给原型,以避免在每个实例中创建数十个插槽的开销。但将此视为减少内存开销的一种方法--仅仅是一种优化。并帮助用户将new的使用隐藏在某种工厂函数的后面,这样他们甚至不需要知道对象是如何创建的。他们只需要知道它有方法foo或属性bar

(请注意,在这种情况下,您不会真正建模古典继承。它仅仅相当于定义一个类来获得共享vtable的效率。)

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3817409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档