Javascript:长度方法有效吗?

san*_*lto 26 javascript arrays immutability

我正在做一些javascript编码,我想知道长度方法是"预先计算",还是由JS引擎记住.

所以,问题是:

如果我经常检查数组长度,并假设我没有更改它(通过闭包使其不可变),我应该预先计算长度方法并将其存储在某个变量中吗?

谢谢!

jos*_*736 26

一如既往,答案是"它取决于".

让我们用百万元素数组测试本机数组:

for (var i = 0; i < arr.length; i++);

var len=arr.length;
for (var i = 0; i < len; i++);
Run Code Online (Sandbox Code Playgroud)

http://josh3736.net/images/arrlen.png

Chrome和Firefox优化属性访问器与将长度复制到局部变量一样高效.IE和Opera没有,而且速度慢了50%.

但是,请记住,测试结果"ops/second"表示通过每秒一百万个元素的数组完成迭代的次数.

为了正确看待这一点,即使在IE8(这一组中表现最差的)中 - 在属性访问和局部变量(分别)上得分为.44和3.9--每次迭代惩罚仅为2μs.迭代超过一千个项目,使用array.length只会花费额外2毫秒.换句话说:提防过早优化.

  • 您应该将图片发布在 Stackoverflow 上,而不是您的个人网站上,因为该网站已不再可用... (3认同)

jfr*_*d00 13

实际数组的长度不是即时计算的.它存储为数组数据结构的一部分,因此访问它不仅仅涉及获取值(没有计算).因此,它通常与检索对象的任何固定属性一样快.正如您在此性能测试中所看到的,检索数组长度和检索对象属性之间基本没有区别:

http://jsperf.com/length-comparisons

一个例外是DOM从诸如getElementsByTagName()或之类的函数返回的nodeList对象getElementsByClassName().在这些中,访问length属性通常要慢得多.这可能是因为这些nodeList对象不是真正的javascript对象,并且每次从这些对象访问某些东西时,Javascript和本机代码之间可能存在桥接.在这种情况下,将长度缓存到局部变量而不是在nodeList的循环中重复使用它会快很多(快10-100倍).我已将其添加到长度比较中,您可以看到它的速度有多慢.

在某些浏览器中,将长度放入局部变量并从那里使用它是有意义的,如果你将一遍又一遍地引用它(如在循环中).这是上面jsperf测试的性能图:


Mik*_*uel 8

所有主要的解释器都为原生数组的长度提供了有效的访问器,但是对于像NodeLists 这样的类似数组的对象则没有.

"在Javascript中高效循环"

Test / Browser                Firefox 2.0 Opera 9.1   Internet Explorer 6
Native For-Loop               155 (ms)    121 (ms)    160 (ms)
...
Improved Native While-Loop    120 (ms)    100 (ms)    110 (ms)
Run Code Online (Sandbox Code Playgroud)

"高效的JavaScript代码"表明

for( var i = 0; i < document.getElementsByTagName('tr').length; i++ ) {
  document.getElementsByTagName('tr')[i].className = 'newclass';
  document.getElementsByTagName('tr')[i].style.color = 'red';
  ...
}
Run Code Online (Sandbox Code Playgroud)
var rows = document.getElementsByTagName('tr');
for( var i = 0; i < rows.length; i++ ) {
  rows[i].className = 'newclass';
  rows[i].style.color = 'red';
  ...
}
Run Code Online (Sandbox Code Playgroud)

这些都不是有效的.getElementsByTagName返回动态对象,而不是静态数组.每次检查循环条件时,Opera都必须重新评估对象,并计算它引用的元素数量,以便计算出length属性.这比检查静态数字需要更多的时间.

  • 当我查看Mozilla的开发人员网络中的数组时,我看不到有关长度的详细信息https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array但是,我会预先计算长度并将其存储在变量只是为了安全.我不认为浏览器共享相同的JS引擎 (2认同)