这话我听过好几次了。JavaScript循环在向后计数时真的更快吗?如果有,为什么?我已经看到了一些测试套件示例,它们显示反向循环更快,但我找不到任何解释!
我假设这是因为循环不再需要在每次检查属性时评估它是否已经完成,它只检查最终的数值。
即。
for (var i = count - 1; i >= 0; i--)
{
// count is only evaluated once and then the comparison is always on 0.
}
这话我听过好几次了。JavaScript循环在向后计数时真的更快吗?如果有,为什么?我已经看到了一些测试套件示例,它们显示反向循环更快,但我找不到任何解释!
我假设这是因为循环不再需要在每次检查属性时评估它是否已经完成,它只检查最终的数值。
即。
for (var i = count - 1; i >= 0; i--)
{
// count is only evaluated once and then the comparison is always on 0.
}
当前回答
既然你对这个主题感兴趣,可以看看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测试中,我得到了以下循环:
其他回答
有时,对代码的编写方式做一些非常小的更改,可能会对代码的实际运行速度产生很大的影响。一个微小的代码更改可能会对执行时间产生很大影响的地方是我们有一个处理数组的for循环。当数组是网页上的元素(如单选按钮)时,这种改变的影响最大,但即使数组是Javascript代码的内部,也值得应用这种改变。
编写for循环来处理数组的常规方法如下:
for (var i = 0; i < myArray.length; i++) {...
The problem with this is that evaluating the length of the array using myArray.length takes time and the way that we have coded the loop means that this evaluation has to be performed every time around the loop. If the array contains 1000 elements then the length of the array will be evaluated 1001 times. If we were looking at radio buttons and had myForm.myButtons.length then it will take even longer to evaluate since the appropriate group of buttons within the specified form must first be located before the length can be evaluated each time around the loop.
显然,我们不希望数组的长度在处理时发生变化,因此所有这些重新计算长度的操作只是不必要地增加了处理时间。(当然,如果你在循环中有添加或删除数组条目的代码,那么数组大小可以在迭代之间改变,所以我们不能改变测试它的代码)
对于一个大小固定的循环,我们能做的就是在循环开始时计算长度,并将其保存在一个变量中。然后,我们可以测试变量以决定何时终止循环。这比每次计算数组长度要快得多,特别是当数组包含多个条目或是网页的一部分时。
这样做的代码是:
for (var i = 0, var j = myArray.length; i < j; i++) {...
因此,现在我们只计算数组的大小一次,并在每次循环中测试循环计数器是否包含该值的变量。访问这个额外的变量比计算数组的大小要快得多,因此我们的代码将比以前运行得快得多。我们的脚本中只有一个额外的变量。
通常情况下,处理数组的顺序并不重要,只要数组中的所有条目都得到了处理。在这种情况下,我们可以通过去掉刚刚添加的额外变量并以相反的顺序处理数组来使代码稍微快一些。
以最有效的方式处理数组的最终代码是:
for (var i = myArray.length-1; i > -1; i--) {...
这段代码仍然只在开始时计算一次数组的大小,但不是将循环计数器与变量进行比较,而是将其与常量进行比较。由于访问常量比访问变量更有效,并且由于我们的赋值语句比以前少了一个,所以第三个版本的代码现在比第二个版本的效率略高,比第一个版本的效率要高得多。
回答这类问题的最好方法就是亲自去尝试。建立一个计算百万次迭代的循环,并以两种方式进行。对两个循环进行计时,并比较结果。
答案可能取决于您使用的浏览器。有些会有不同的结果。
i——或i++占用的时间并不多。如果你深入到CPU架构中,++比——更快,因为——操作会做2的补位,但它发生在硬件内部,所以这将使它更快,而且++和——之间没有太大的区别,而且这些操作被认为是CPU消耗的时间最少的。
for循环是这样运行的:
在开始时初始化变量一次。 检查循环的第二个操作数中的约束,<,>,<=等。 然后应用循环。 递增循环,循环再次抛出这些进程。
所以,
for (var i = Things.length - 1; i >= 0; i--) {
Things[i]
};
将计算数组的长度只有一次在开始时,这不是很多时间,但是
for(var i = array.length; i--; )
将计算每个循环的长度,因此它将消耗大量时间。
我想为这个线程贡献最快的JavaScript循环,是跨浏览器的!与反向while循环相比,该循环的性能提高了500%以上。
我的博客:JavaScript中最快的循环
我在《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上的基准测试)。