这话我听过好几次了。JavaScript循环在向后计数时真的更快吗?如果有,为什么?我已经看到了一些测试套件示例,它们显示反向循环更快,但我找不到任何解释!

我假设这是因为循环不再需要在每次检查属性时评估它是否已经完成,它只检查最终的数值。

即。

for (var i = count - 1; i >= 0; i--)
{
  // count is only evaluated once and then the comparison is always on 0.
}

当前回答

我在jsbench上做了一个比较。

正如alestani指出的那样,在升序循环中需要花费时间的一件事是,对于每次迭代,计算数组的大小。在这个循环中:

for ( var i = 1; i <= array.length; i++ )

每次增加i,你就计算。length。

for ( var i = 1, l = array.length; i <= l; i++ )

当你声明i时,你只对.length求值一次。

for ( var i = array.length; i--; )

比较是隐式的,它发生在i递减之前,并且代码非常可读。然而,你在循环中放入的东西会产生很大的不同。

循环调用函数(在其他地方定义):

for (i = values.length; i-- ;) {
  add( values[i] );
}

内联代码循环:

var sum = 0;
for ( i = values.length; i-- ;) {
  sum += values[i];
}

如果你可以内联你的代码,而不是调用一个函数,而不牺牲易读性,你可以有一个数量级的速度循环!


注意:由于浏览器越来越擅长内联简单的函数,这实际上取决于你的代码有多复杂。所以,先配置再优化,因为

瓶颈可能在其他地方(ajax, reflow,…) 你可以选择一个更好的算法 您可以选择更好的数据结构

但是请记住:

代码是为了让人阅读而写的,只是顺便让机器执行。

其他回答

好吧,我不了解JavaScript,它应该只是一个重新计算数组长度的问题,也许与关联数组有关(如果你只是递减,不太可能需要分配新条目——如果数组是密集的,也就是说。有人可能会为此进行优化)。

在低级汇编中,有一个循环指令,称为DJNZ(如果非零则递减和跳跃)。因此,递减和跳转都在一条指令中,使得它可能比INC和JL / JB略快(递增,如果小于则跳转/如果低于则跳转)。同样,与零比较比与其他数字比较简单。但所有这些都是边缘的,也取决于目标架构(可能会产生不同,例如智能手机上的Arm)。

我没想到这种低级别的差异会对解释语言产生这么大的影响,我只是在回答中没有看到DJNZ,所以我想分享一个有趣的想法。

我不认为在JavaScript中说I比i++更快是有意义的。

首先,它完全依赖于JavaScript引擎实现。

其次,如果最简单的构造被JIT化并转换为本机指令,那么i++ vs i——将完全依赖于执行它的CPU。也就是说,在arm(移动电话)上,下降到0更快,因为递减和比较0是在一条指令中执行的。

也许,你认为一个比另一个更浪费,因为建议的方式是

for(var i = array.length; i--; )

但建议的方式不是因为一个比另一个快,而只是因为如果你写

for(var i = 0; i < array.length; i++)

然后是每个迭代数组。length必须被计算(更聪明的JavaScript引擎可能会发现循环不会改变数组的长度)。尽管它看起来像一个简单的语句,但它实际上是JavaScript引擎在底层调用的某个函数。

The other reason, why i-- could be considered "faster" is because JavaScript engine needs to allocate only one internal variable to control the loop (variable to the var i). If you compared to array.length or to some other variable then there had to be more than one internal variable to control the loop, and the number of internal variables are limited asset of a JavaScript engine. The less variables are used in a loop the more chance JIT has for optimization. That's why i-- could be considered faster...

曾经有人说——i(在c++中)更快,因为只有一个结果,即递减的值。I——需要将减后的值存储回I,并保留原始值作为结果(j = I——;)。在大多数编译器中,这会占用两个而不是一个寄存器,这可能会导致另一个变量必须写入内存,而不是作为寄存器变量保留。

我同意其他人的看法,他们说现在没有什么不同。

++还是——并不重要,因为JavaScript是一种解释型语言,而不是编译型语言。每条指令都翻译成一种以上的机器语言,你不应该关心那些血腥的细节。

那些谈论使用——(或++)来有效使用汇编指令的人是错误的。这些指令适用于整数算术,在JavaScript中没有整数,只有数字。

您应该编写可读的代码。

简单地说

“i——和i++。实际上,它们都需要相同的时间。”

但在这种情况下,当你进行增量操作。处理器计算.length每个时间变量都加1,如果减量..特别是在这种情况下,它只计算一次。length直到得到0。