"锁定"JavaScript对象的任何性能优势?

cal*_*lum 66 javascript ecmascript-5 javascript-1.8

JavaScript 1.8.5(ECMAScript 5)添加了一些有趣的方法,可以防止将来修改传递的对象,具有不同程度的彻底性:

据推测,这些问题的关键在于捕获错误:如果您知道在某个点之后不想修改对象,则可以将其锁定,以便在以后无意中尝试修改时会抛出错误.("use strict";假设你已经完成了.)

我的问题:在现代JS引擎(如V8)中,使用上述方法锁定对象时是否有任何性能优势(例如,更快的属性查找,减少内存占用)?

(另请参阅John Resig的好解释 - 但不提及性能.)

Jan*_*lak 77

还有的是没有什么区别,因为至少铬47.0.2526.80(64位)的性能.

Testing in Chrome 6.0.3359 on Mac OS 10.13.4
-----------------------------------------------
Test               Ops/sec
non-frozen object  106,825,468  ±1.08%  fastest
frozen object      106,176,323  ±1.04%  fastest
Run Code Online (Sandbox Code Playgroud)

性能测试(可在http://jsperf.com/performance-frozen-object获得):

  const o1 = {a: 1};
  const o2 = {a: 1};

  Object.freeze(o2);

  // Non-frozen object:
  for(var key in o1);

  // Frozen object:
  for(var key in o2);
Run Code Online (Sandbox Code Playgroud)

更新03.05.2018:Chrome 66.0.3359(64位)的性能没有差异

更新06.03.2017:Chrome 56.0.2924(64位)的性能没有差异

2015年12月13日更新:Chrome 47.0.2526.80(64位)的性能没有差异


对于Chrome 34,在@ pimvdb的测试用例中,冻结对象的性能略好于非冻结对象(结果如下).然而,这种差异似乎不足以证明使用这种技术来提高性能.

http://jsperf.com/performance-frozen-object

Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test               Ops/sec
non-frozen object  105,250,353  ±0.41%  3% slower
frozen object      108,188,527  ±0.55%  fastest
Run Code Online (Sandbox Code Playgroud)

运行@kangax的测试用例表明,该对象的两个版本的执行情况大致相同:

http://jsperf.com/performance-frozen-object-prop-access

Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test               Ops/sec
non-frozen object  832,133,923  ±0.26%  fastest
frozen object      832,501,726  ±0.28%  fastest
Run Code Online (Sandbox Code Playgroud)

http://jsperf.com/http-jsperf-com-performance-frozen-object-instanceof

Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test               Ops/sec
non-frozen object  378,464,917  ±0.42%  fastest
frozen object      378,705,082  ±0.24%  fastest
Run Code Online (Sandbox Code Playgroud)

  • 我有一个案例,调用 Object.freeze() 本身对性能不利,因为我有许多不同的小对象(想想大树的节点)。结果证明这个结构太重了,所以我放弃了 Object.freeze()。 (2认同)

pim*_*vdb 14

在谷歌浏览器中(所以是V8),冻结对象的迭代速度比常规对象慢98%.

http://jsperf.com/performance-frozen-object

Test name*              ops/sec

non-frozen object    32,193,471
frozen object           592,726
Run Code Online (Sandbox Code Playgroud)

可能这是因为这些功能相对较新,可能尚未优化(但这只是我的猜测,老实说我不知道​​原因).

无论如何,我真的不建议将它用于性能优势,因为这显然没有意义.


*测试代码是:

var o1 = {a: 1};
var o2 = {a: 1};

Object.freeze(o2);
Run Code Online (Sandbox Code Playgroud)

测试1(非冷冻物体):

for(var key in o1);
Run Code Online (Sandbox Code Playgroud)

测试2(冷冻对象):

for(var key in o2);
Run Code Online (Sandbox Code Playgroud)

编辑:

由于这个答案是最初编写的,因此导致此问题的V8中的错误已得到修复.请参阅Jan Molak上面的回答

  • 现在(在Chrome 34和2014年),冻结对象的迭代似乎迭代速度提高了约24%. (19认同)
  • 这听起来像是一个V8 bug,而不是那些没有优化的东西.注意[Object.keys](http://jsperf.com/performance-frozen-object/2)仅慢72% (6认同)
  • 现在这已经过时了,贬低了. (6认同)
  • @Raynos:好点; ``Object.keys`也不应该*慢*.我同意它更像是一个bug,因为冻结不应该是性能损失; 恰恰相反. (3认同)
  • 有趣的发现.我检查了其他浏览器 - 夜间FF,WebKit的,Opera和他们都没有这样的疯狂放缓(见[jsperf(http://jsperf.com/performance-frozen-object)).绝对看起来像一个bug.我在V8跟踪提起的一个问题 - http://code.google.com/p/v8/issues/detail?id=1858 (3认同)
  • 不再是真的http://jsperf.com/freeze-vs-seal-vs-normal/19因为多年来Chrome的多次提交. (3认同)

Ray*_*nos 11

从理论上讲,冻结物体可以让你对物体的形状做出更有力的保证.

这意味着VM可以压缩内存大小.

这意味着VM可以优化原型链中的属性查找.

这意味着任何实时引用都变得不活了,因为对象不能再改变了.

实际上,JavaScript引擎尚未进行这些积极的优化.


lla*_*bda 5

截至2013年6月20日,V8优化了Object.freeze.截至2014年12月10日,Object.seal和Object.preventExtensions已经优化.请参阅问题https://code.google.com/p/chromium/issues/detail?id= 115960