在 另一个问题 中,用户指出 new
关键字使用起来很危险,并提出了一种不使用 new
的对象创建解决方案。我不相信那是真的,主要是因为我使用了 Prototype 、 Script.aculo.us 和其他优秀的 JavaScript 库,并且他们每个人都使用了 new
关键字。
尽管如此,昨天我在 YUI 剧院观看了 Douglas Crockford 的演讲,他说了完全相同的话,他没有在他的代码中使用 new
关键字( Crockford on JavaScript - Act III:功能终极 - 50:23 分钟)。
使用 new
关键字是否“不好”?使用它有什么优点和缺点?
原文由 Pablo Fernandez 发布,翻译遵循 CC BY-SA 4.0 许可协议
Crockford 为推广优秀的 JavaScript 技术做了很多工作。他对语言关键要素的固执己见引发了许多有益的讨论。也就是说,有太多人将每一个“坏”或“有害”的声明都当作福音,拒绝超越一个人的意见。有时可能会有点令人沮丧。
与从头开始构建每个对象相比,使用
new
关键字提供的功能有几个优点:new
关键字是使用它的规范(并且唯一可用的跨平台)方式。prototype
并使用new
消除新对象。这不仅速度更快(原型上的每个方法都不需要代码),它还避免了为每个方法使用单独的属性来膨胀每个对象。在较慢的机器上(或者尤其是较慢的 JS 解释器),当创建许多对象时,这可能意味着时间和内存的显着节省。是的,
new
有一个关键的缺点,其他答案巧妙地描述了这一缺点:如果您忘记使用它,您的代码将在没有警告的情况下中断。幸运的是,这个缺点很容易减轻——只需向函数本身添加一些代码:现在您可以拥有
new
的优势,而不必担心不小心误操作造成的问题。John Resig 在他的 简单“类”实例化 帖子中详细介绍了这项技术,并包括一种默认情况下将此行为构建到您的“类”中的方法。绝对值得一读……就像他即将出版的书 《JavaScript 忍者的秘密》 一样,它在这个和 JavaScript 语言的许多其他“有害”特性中发现了隐藏的黄金(关于
with
的 章节 特别有启发性对于我们这些最初将这个饱受诟病的功能视为噱头的人来说)。通用完整性检查
您甚至可以在检查中添加一个断言,如果您认为损坏的代码会默默地工作,这会困扰您。或者,正如 一些人 评论的那样,使用检查来引入运行时异常:
请注意,此代码段能够避免对构造函数名称进行硬编码,因为与前面的示例不同,它不需要实际实例化对象 - 因此,可以将其复制到每个目标函数中而无需修改。
ES5带走
正如 Sean McMillan 、 stephenbez 和 jrh 所指出的,使用
arguments.callee
在 ES5 的 严格模式下 是无效的。因此,如果您在该上下文中使用上述模式,将会抛出错误。ES6 和一个完全无害的
new
ES6 将 类 引入 JavaScript——不,不是像老派 Crockford 那样采用奇怪的 Java 模仿方式,而是在精神上更像是他(和其他人)后来采用的轻量级方式,利用原型继承的最佳部分和将通用模式烘焙到语言本身。
…其中一部分包括一个保险箱
new
:但是,如果您 不想 使用新糖怎么办?如果您只想使用上面显示的那种安全检查来更新您完美无缺的旧式原型代码,以便它们继续在严格模式下工作怎么办?
好吧,正如 Nick Parsons 指出 的那样,ES6 也以
new.target
的形式提供了一个方便的检查:因此,无论您选择哪种方法,您都可以 - 稍微考虑一下并保持良好的卫生习惯 - 使用
new
而不会造成伤害。