Crockford 在推广优秀的 JavaScript 技术方面做了很多工作。他对语言关键要素的固执己见引发了许多有益的讨论。也就是说,有太多的人把每一个“坏”或“有害”的宣言都当作福音,拒绝超越一个人的意见。有时可能会有点令人沮丧。
new
与从头开始构建每个对象相比,使用关键字提供的功能有几个优点:
- 原型继承。尽管习惯于基于类的面向对象语言的人经常带着怀疑和嘲笑的眼光看待 JavaScript,但 JavaScript 的本机继承技术是一种简单且非常有效的代码重用手段。并且 new 关键字是使用它的规范(且唯一可用的跨平台)方法。
- 表现。这是#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 在他的Simple“Class”Instantiation帖子中详细介绍了这种技术,并在默认情况下包含了一种将此行为构建到“类”中的方法。绝对值得一读……就像他即将出版的书一样,JavaScript Ninja 的秘密,它在 JavaScript 语言的这个特性和许多其他“有害”特性中找到了隐藏的金子(这一章对with
我们这些最初不屑一顾的人特别有启发性)这个备受诟病的功能是一个噱头)。