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毫秒.换句话说:提防过早优化.
jfr*_*d00 13
实际数组的长度不是即时计算的.它存储为数组数据结构的一部分,因此访问它不仅仅涉及获取值(没有计算).因此,它通常与检索对象的任何固定属性一样快.正如您在此性能测试中所看到的,检索数组长度和检索对象属性之间基本没有区别:
http://jsperf.com/length-comparisons
一个例外是DOM从诸如getElementsByTagName()
或之类的函数返回的nodeList对象getElementsByClassName()
.在这些中,访问length属性通常要慢得多.这可能是因为这些nodeList对象不是真正的javascript对象,并且每次从这些对象访问某些东西时,Javascript和本机代码之间可能存在桥接.在这种情况下,将长度缓存到局部变量而不是在nodeList的循环中重复使用它会快很多(快10-100倍).我已将其添加到长度比较中,您可以看到它的速度有多慢.
在某些浏览器中,将长度放入局部变量并从那里使用它是有意义的,如果你将一遍又一遍地引用它(如在循环中).这是上面jsperf测试的性能图:
所有主要的解释器都为原生数组的长度提供了有效的访问器,但是对于像NodeList
s 这样的类似数组的对象则没有.
Run Code Online (Sandbox Code Playgroud)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)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'; ... }
这些都不是有效的.
getElementsByTagName
返回动态对象,而不是静态数组.每次检查循环条件时,Opera都必须重新评估对象,并计算它引用的元素数量,以便计算出length
属性.这比检查静态数字需要更多的时间.
归档时间: |
|
查看次数: |
8340 次 |
最近记录: |