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

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

即。

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

当前回答

并不是说i比i++快。实际上,它们都一样快。

在升序循环中需要花费时间的是,对于每个i,计算数组的大小。在这个循环中:

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

当你声明i时,你只对.length求值一次,而对于这个循环

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

当你检查i是否<= array.length时,你每次增加i就计算.length。

在大多数情况下,您甚至不应该担心这种优化。

其他回答

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

a++ < length

实际编译为

a++
test (a-length)

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

既然你对这个主题感兴趣,可以看看Greg Reimer关于JavaScript循环基准的博客文章,用JavaScript编写循环的最快方法是什么?:

我为JavaScript中不同的循环编码方式构建了一个循环基准测试套件。现在已经有一些这样的工具了,但是我还没有找到任何一个能够区分原生数组和HTML集合的工具。

您还可以通过打开https://blogs.oracle.com/greimer/resource/loop-test.html对循环进行性能测试(如果JavaScript在浏览器中被NoScript阻塞,则无法工作)。

编辑:

Milan Adamovsky最近创建的基准测试可以在运行时针对不同的浏览器执行。

在Mac OS X 10.6上的Firefox 17.0测试中,我得到了以下循环:

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

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

我在《Sublime Text 2》中看到了同样的建议。

如前所述,主要的改进不是在for循环的每次迭代中计算数组的长度。这是一种众所周知的优化技术,当数组是HTML文档的一部分时,在JavaScript中特别有效(为所有li元素执行for)。

例如,

For (var I = 0;i < document.getElementsByTagName('li').length;我+ +)

慢得多

for (was i = 0, len = document.getElementsByTagName('li').length; in < fief; i++)

在我看来,你的问题中表单的主要改进是它没有声明一个额外的变量(在我的例子中是len)

但如果你问我,我认为重点不在于i++ vs i——优化,而在于不必在每次迭代时计算数组的长度(您可以看到jsperf上的基准测试)。

首先,i++和i——在任何编程语言(包括JavaScript)上花费的时间完全相同。

下面的代码花费的时间大不相同。

快速:

for (var i = 0, len = Things.length - 1; i <= len; i++) { Things[i] };

慢:

for (var i = 0; i <= Things.length - 1; i++) { Things[i] };

因此,下面的代码也需要不同的时间。

快速:

for (var i = Things.length - 1; i >= 0; i--) { Things[i] };

慢:

for (var i = 0; i <= Things.length - 1; i++) { Things[i] };

附:由于编译器的优化,Slow只适用于少数语言(JavaScript引擎)。最好的方法是用'<'代替'<='(或'='),用'——i'代替'i——'。