array.forEach比本机迭代运行得更快?怎么样?

时间:2012-04-02 18:17:36

标签: javascript performance testing

http://jsperf.com/testing-foreach-vs-for-loop

据我所知,测试案例2的运行速度应该比测试案例1慢 - 我想看看速度有多慢。当我看到它运行得更快时,想象一下我的惊喜!

这里发生了什么?在幕后优化?或者.forEach更清洁,更快?

在Windows Server 2008 R2 / 7 64位上的Chrome 18.0.1025.142 32位测试

5 个答案:

答案 0 :(得分:9)

有许多迭代优化导致您的for循环丢失,例如:

  • 缓存数组长度
  • 向后迭代
  • 使用++ counter而不是counter ++

这些是我听过和使用过的,我相信还有更多。如果内存对我有用,那么向后迭代while循环是所有循环结构中最快的(在大多数浏览器中)。

有关示例,请参阅this jsperf

编辑: postfix vs prefix perf testiterating backwards的链接。 我无法找到使用+ = 1而不是++的参考,所以我已将其从列表中删除。

答案 1 :(得分:3)

更新:

这些答案中的许多旧技巧对于旧版浏览器中的解释JS非常有用。

在任何现代JS实现中,包括所有现代浏览器,Node和最新的移动Web视图,内联函数实际上可以由JIT(JS编译器)缓存,通常使得forEach更快速地进行数组迭代。过去只是反复调用函数需要一个可能严重降低非平凡循环性能的构建/拆除过程。

为了获得最佳性能,我将避免引用任何未作为参数传递或在函数内部定义的内容(如果您不需要)。我不是百分百肯定这很重要,但我可以理解为什么会这样。

涉及任何类型的查找过程(如数组长度或DOM节点属性)的Getter值可能仍然最好缓存到变量。

但除此之外,我试图让避免工作的基本原则指导你的工作。预先计算不需要在循环中重新计算的事物,或者将查询选择器结果缓存到var而不是在DOM中反复搜索这些都是很好的例子。尝试过于努力以利用JIT行为可能会变得非常神秘,并且不太可能随着时间推移或跨越所有JIT而停滞不前。

老答案:

好的,忘了文字墙。要点:

var i = someArray.length; //length is cached
someArray.reverse(); //include this only if iterating in 0-(length-1) order is important

while(i--){
//run a test statement on someArray[i];
}
  • 长度被缓存并立即进入索引

  • 在JS AFAIK中向后迭代的好处是避免使用两个操作数的逻辑运算符。在这种情况下,我们只是评估一个数字。这是真的,或者是零和假。

  • 我也觉得它很优雅。

答案 2 :(得分:1)

在每次迭代时从length读取array可能会很慢,但是每次运行速度都比较慢,因为函数调用在js中并不便宜。

PS:forEach在FF10上慢了14%。

答案 3 :(得分:0)

他们在Opera中与我大致相同。需要注意的是,for()中的条件是array.length。如果在变量中缓存数组的长度,然后循环,则应该看到更好的性能。

答案 4 :(得分:0)

也许for()更慢,因为循环将'array.length'应用于每次迭代,以获得数组的长度。

尝试:

var nri = array.length;
for( var i = 0; i < nri; i++ ){
   // ...
}