史蒂夫·桑德斯(Steve Sounders)在他的书Even Faster Web Sites中写道,提高循环性能的一种简单方法是将迭代器递减为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
,它将被解释为0 == false
,并且循环结束。 该表达式在每次循环迭代结束时进行评估(在下一次条件评估之前)。这里不需要它,它是空的。这三个表达式在for循环中都是可选的。
for循环语法不是问题的一部分,但是因为有点不常见,所以我认为对其进行澄清很有趣。也许它之所以更快的一个原因是,因为它使用了更少的表达式(ojit_code“trick”)。
最佳答案
我不确定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/