在他的书中Even Faster Web Sites Steve Sounders 写道,提高循环性能的一种简单方法是将迭代器递减到 0,而不是递增到总长度(实际上该章节是由 Nicholas C. Zakas 编写的)。根据每次迭代的复杂性,此更改最多可节省原始执行时间的 50%。例如:
var values = [1,2,3,4,5];
var length = values.length;
for (var i=length; i--;) {
process(values[i]);
}
这与 for
循环、do-while
循环和 while
循环几乎相同。
请问这是什么原因呢? 为什么递减迭代器要快得多?(我感兴趣的是这方面的技术背景,而不是证明这一说法的基准测试。)
编辑:乍一看,这里使用的循环语法看起来是错误的。没有 length-1
或 i>=0
,所以让我们澄清一下(我也很困惑)。
这是一般的 for 循环语法:
for ([initial-expression]; [condition]; [final-expression])
statement
初始表达式 -
var i=length
首先评估此变量声明。
条件 -
i--
此表达式在每次循环迭代之前求值。它会在第一次通过循环之前递减变量。如果此表达式的计算结果为
false
,则循环结束。在 JavaScript 中是0 == false
所以如果i
最终等于0
它被解释为false
并且循环结束.最终表达式
此表达式在每次循环迭代结束时求值(在下一次求值条件之前)。这里不需要它,它是空的。所有三个表达式在 for 循环中都是可选的。
for 循环语法不是问题的一部分,但因为它有点不常见,所以我认为澄清它很有趣。也许它更快的一个原因是因为它使用了更少的表达式(0 == false
“技巧”)。
最佳答案
我不确定 Javascript,在现代编译器下它可能无关紧要,但在“过去”这段代码中:
for (i = 0; i < n; i++){
.. body..
}
会产生
move register, 0
L1:
compare register, n
jump-if-greater-or-equal L2
-- body ..
increment register
jump L1
L2:
而后向计数代码
for (i = n; --i>=0;){
.. body ..
}
会产生
move register, n
L1:
decrement-and-jump-if-negative register, L2
.. body ..
jump L1
L2:
所以在循环内部它只执行了两个额外的指令而不是四个。
关于JavaScript 循环性能 - 为什么将迭代器递减到 0 比递增更快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30159842/