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

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

即。

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

当前回答

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

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

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

其他回答

不是——或++,而是比较操作。使用——,你可以使用与0比较,而使用++,你需要与长度比较。在处理器上,与零的比较通常是可用的,而与有限整数的比较则需要减法。

a++ < length

实际编译为

a++
test (a-length)

所以它在编译时在处理器上花费的时间更长。

它取决于数组在内存中的位置,以及访问该数组时内存页面的命中率。

在某些情况下,按列顺序访问数组成员比按行顺序访问快,因为命中率增加了。

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

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

在许多情况下,这本质上与处理器比其他比较更快地比较0这一事实无关。

这是因为只有少数Javascript引擎(JIT列表中的那些)真正生成机器语言代码。

大多数Javascript引擎构建源代码的内部表示,然后对其进行解释(要了解这是什么样子,请查看Firefox的SpiderMonkey页面底部附近)。一般来说,如果一段代码实际上做同样的事情,但导致更简单的内部表示,它将运行得更快。

请记住,对于简单的任务,如从一个变量中添加/减去一个,或将一个变量与某个东西进行比较,解释器从一个内部“指令”移动到下一个“指令”的开销是相当高的,因此JS引擎内部使用的“指令”越少越好。

我最后一次为它烦恼是在编写6502程序集时(8位,是的!)最大的收获是大多数算术操作(特别是减数)更新了一组标志,其中一个是Z,“达到零”指示符。

因此,在循环的最后,您只执行了两条指令:DEC(减量)和JNZ(如果不是零则跳),不需要进行比较!