JavaScript的“新”关键字是否有害?

在另一个问题中,一位用户指出, new关键字使用起来很危险,并提出了一个解决方案来创建不使用new对象。 我不相信这是真的,主要是因为我使用了Prototype,Scriptaculous和其他优秀的JavaScript库,并且每个人都使用new关键字。

尽管如此,昨天我在YUI剧院观看道格拉斯克罗克福德的讲话,他说完全一样的东西,他没有在他的代码中使用new关键字(Crockford on JavaScript - Act III:Function the Ultimate - 50: 23分钟)。

使用new关键字是'坏'吗? 使用它的优点和缺点是什么?


Crockford为推广优秀的JavaScript技术做了很多工作。 他对该语言关键要素的opinion持立场引发了许多有益的讨论。 也就是说,有太多的人把每一个宣称“坏”或“有害”的福音当作福音,拒绝超越一个人的意见。 有时可能有点令人沮丧。

使用new关键字提供的功能与从零开始构建每个对象相比具有几个优点:

  • 原型继承。 虽然习惯于基于类的面向对象语言的人常常怀疑混合了怀疑和嘲笑,但JavaScript的本地继承技术是代码重用的一种简单且令人惊讶的有效方式。 而新的关键字是使用它的规范(并且只有可用的跨平台)手段。
  • 性能。 这是#1的一个副作用:如果我想为每个创建的对象添加10个方法,我只需编写一个创建函数,手动将每个方法分配给每个新对象......或者,我可以将它们分配给创造功能的prototype并使用new来消除新的对象。 这不仅更快(原型上的每个方法都不需要代码),它避免了每个方法使用不同的属性膨胀每个对象。 在较慢的机器上(尤其是较慢的JS解释器),当创建多个对象时,这可能意味着显着节省时间和内存。
  • 是的, new有一个关键的缺点,由其他答案巧妙地描述:如果你忘记使用它,你的代码将会中断而没有任何警告。 幸运的是,该缺点很容易缓解 - 只需向函数本身添加一些代码即可:

    function foo()
    {
       // if user accidentally omits the new keyword, this will 
       // silently correct the problem...
       if ( !(this instanceof foo) )
          return new foo();
    
       // constructor logic follows...
    }
    

    现在,您可以拥有new的优势,而不必担心由于意外滥用而造成的问题。 你甚至可以在检查中添加一个断言,看看是否存在破坏代码的默认工作方式。 或者,如一些评论所述,使用检查来引入运行时异常:

    if ( !(this instanceof arguments.callee) ) 
       throw new Error("Constructor called as a function");
    

    (请注意,这段代码能够避免对构造函数名称进行硬编码,与之前的示例不同,它不需要实际实例化对象 - 因此,它可以不加修改地复制到每个目标函数中。)

    John Resig在他简单的“类”实例化文章中详细介绍了这种技术,并且默认包括将这种行为构建到“类”中的方法。 绝对值得一读...这是他即将出版的新书中,JavaScript的忍者的秘密,其中认定隐金在这方面和JavaScript语言的许多其他“有害”的特点(上 with是对我们这些谁最初有启发作为一个噱头解雇了这个备受争议的功能)。


    我刚刚读过他的Crockfords书“Javascript:The Good Parts”的一些部分。 我感觉他认为所有曾经把他咬过的东西都是有害的:

    关于切换过程:

    我绝不允许切换案例进入下一个案例。 有一次,我在代码中发现了一个错误,这个错误是由于意外跌落而发生的,之后立即发表了关于为什么有时会有用的有力讲话。 (第97页,ISBN 978-0-596-51774-8)

    关于++和 -

    众所周知,++(增量)和 - (减量)运算符通过鼓励恶意代码来促成错误的代码。 在启用病毒和其他安全威胁方面,它们仅次于错误的体系结构。 (第122页)

    关于新:

    如果您在调用构造函数时忘记包含新前缀,则不会绑定到新对象。 可悲的是,这将被绑定到全局对象,所以不会增加新的对象,而是会打断全局变量。 这真的很糟糕。 没有编译警告,并且没有运行时警告。 (第49页)

    还有更多,但我希望你能得到照片。

    我对你的问题的回答: 不,这没有害处。 但是如果你忘记使用它,当你应该可以有一些问题时。 如果你在良好的环境中发展,你会注意到这一点。

    更新

    在答复写了大约一年后,第五版ECMAScript发布了,支持严格模式。 在严格模式下, this不再局限于全局对象,而是undefined


    Javascript是一种动态语言,有很多种方法可以让另一种语言阻止你。

    基于你可能会搞砸的原因,避免使用new的基本语言功能有点像在你穿过雷区之前去除你闪亮的新鞋子,以防万一你可能会让你的鞋子变得泥泞。

    我使用一个约定,其中函数名以小写字母开头,实际上类定义的“函数”以大写字母开头。 结果是一个非常引人注目的视觉线索,“语法”是错误的: -

    var o = MyClass();  // this is clearly wrong.
    

    在这个良好的命名习惯帮助之上。 在所有的功能都做了事情之后,因此它的名字中应该有一个动词,而类代表对象,并且是没有动词的名词和形容词。

    var o = chair() // Executing chair is daft.
    var o = createChair() // makes sense.
    

    它有趣的是如何SO的语法着色解释了上面的代码。

    链接地址: http://www.djcxy.com/p/6975.html

    上一篇: Is JavaScript's "new" keyword considered harmful?

    下一篇: Deep copy (clone) of an object with matrix (Java)