我已经听过好几次了。向后计数时 JavaScript 循环真的更快吗?如果是这样,为什么?我已经看到一些测试套件示例表明反向循环更快,但我找不到任何关于原因的解释!
我假设这是因为循环不再需要在每次检查属性是否完成时都评估它,它只检查最终的数值。
IE
for (var i = count - 1; i >= 0; i--)
{
// count is only evaluated once and then the comparison is always on 0.
}
我已经听过好几次了。向后计数时 JavaScript 循环真的更快吗?如果是这样,为什么?我已经看到一些测试套件示例表明反向循环更快,但我找不到任何关于原因的解释!
我假设这是因为循环不再需要在每次检查属性是否完成时都评估它,它只检查最终的数值。
IE
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--;)
你.length
只评估一次,当你声明时i
,而对于这个循环
for(var i = 1; i <= array.length; i++)
您评估.length
每次递增时i
,当你检查i <= array.length
。
在大多数情况下,您甚至不必担心这种优化。
我试图用这个答案给出一个广泛的画面。
在我最近测试这个问题之前,括号中的以下想法是我的信念:
[[对于像C / C++这样的低级语言,代码经过编译,以便处理器在变量为零(或非零)时具有特殊的条件跳转命令。
此外,如果您关心这么多优化,您可以使用代替,因为它是一个单处理器命令,而意味着.]] ++i
i++
++i
i++
j=i+1, i=j
真正快速的循环可以通过展开它们来完成:
for(i=800000;i>0;--i)
do_it(i);
它可能比
for(i=800000;i>0;i-=8)
{
do_it(i); do_it(i-1); do_it(i-2); ... do_it(i-7);
}
但这其中的原因可能相当复杂(顺便提一下,游戏中存在处理器命令预处理和缓存处理的问题)。
就高级语言而言,如您所问的JavaScript,如果您依赖库、用于循环的内置函数,则可以优化事物。让他们决定如何最好地完成。
因此,在 JavaScript 中,我建议使用类似
array.forEach(function(i) {
do_it(i);
});
它也不太容易出错,浏览器有机会优化您的代码。
[备注:不仅是浏览器,您也有空间可以轻松优化,只需重新定义forEach
功能(取决于浏览器),使其使用最新的最佳技巧!:) @AMK 说在特殊情况下值得使用array.pop
or array.shift
。如果你这样做,把它放在窗帘后面。的最大矫枉过正是添加选项,forEach
选择循环算法。]
此外,对于低级语言,如果可能的话,最好的做法是使用一些智能库函数进行复杂的循环操作。
这些库还可以将东西(多线程)放在背后,并且专业的程序员也会使它们保持最新状态。
我做了更多的审查,结果证明在 C/C++ 中,即使对于 5e9 = (50,000x100,000) 操作,如果测试是针对像@alestanis 所说的常量进行的,则上升和下降之间没有区别。(JsPerf 结果有时不一致,但总的来说是一样的:你不能产生很大的不同。)
所以--i
恰好是一个“豪华”的东西。它只会让你看起来像一个更好的程序员。:)
另一方面,对于在这种 5e9 情况下展开,它使我从 12 秒下降到 10 秒时的 2.5 秒,以及 20 秒时的 2.1 秒。它没有优化,而优化已将事情缩短到无法衡量的时间。:) (展开可以按照我上面的方式或使用 完成i++
,但这并不能在 JavaScript 中取得进展。)
总而言之:保持i--
/i++
和++i
/i++
与工作面试的差异,坚持array.forEach
或其他复杂的库功能(如果可用)。;)
i--
一样快 i++
下面的代码和你的一样快,但使用了一个额外的变量:
var up = Things.length;
for (var i = 0; i < up; i++) {
Things[i]
};
建议不要每次都评估数组的大小。对于大阵列,可以看到性能下降。
因为您对该主题感兴趣,所以请查看 Greg Reimer 的关于 JavaScript 循环基准测试的博客文章,在 JavaScript 中编写循环的最快方法是什么?:
我为在 JavaScript 中编码循环的不同方式构建了一个循环基准测试套件。已经有一些这样的,但我没有发现任何承认本机数组和 HTML 集合之间的区别。
您还可以通过打开对循环进行性能测试https://blogs.oracle.com/greimer/resource/loop-test.html
(如果 JavaScript 在浏览器中被NoScript 等阻止,则不起作用)。
编辑:
米兰Adamovsky创建一个更近的基准可以在运行时进行此不同的浏览器。