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

array.forEach running faster than native iteration? How?

本文关键字:怎样 运行 forEach 本机 迭代 array      更新时间:2023-09-26

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

我的理解是,测试用例2应该比测试用例1运行得慢——我想看看运行得慢多少。想象一下,当我看到它跑得更快时,我的惊讶!

这是怎么回事?幕后优化?或者是。for每个人都更干净更快?

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

for循环缺少许多迭代优化,例如:

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

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

有关一些示例,请参阅此jsperf。

编辑:postfix与prefix perf测试和向后迭代的链接。我找不到使用+=1而不是++的引用,所以我已将其从列表中删除。

更新:

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

在任何现代JS实现中,包括所有现代浏览器、Node和最新的移动Web视图,内联函数实际上都可以由JIT(JS编译器)缓存,这通常使forEach成为数组迭代的更快选项。过去情况正好相反,只需重复调用一个函数就需要一个构建/拆卸过程,这可能会严重降低非平凡循环的性能。

为了获得最佳性能,如果不必要的话,我会避免引用任何没有作为参数传递或在函数内部定义的内容。我不能100%确定这是否重要,但我可以理解为什么会这样。

涉及任何类型的查找过程(如数组长度或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中向后迭代的好处是避免使用具有两个操作数的逻辑运算符。在这种情况下,我们只是在评估一个数字。这是真的,或者是零和假。

  • 我也觉得它很优雅。

在每次迭代时从array读取length可能很慢,但forEach通常较慢,因为函数调用在js中不是廉价的操作。

PS:forEach比FF10慢14%。

在Opera中,它们对我来说大致相同。需要注意的是,for()中的条件是array.length。如果将数组的长度缓存在一个变量中,然后循环,您应该会看到更好的性能。

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

尝试:

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