为什么向后遍历数组比向前更快

时间:2011-12-31 17:41:12

标签: javascript performance optimization

鉴于此代码:

var arr = [];

for (var i = 0; i < 10000; ++i)
    arr.push(1);

转发

for (var i = 0; i < arr.length; ++i) {}

向后

for (var i = arr.length - 1; i >= 0; --i) {}

硬编码转发

for (var i = 0; i < 10000; ++i) {}

为什么向后退得这么快?

以下是测试: http://jsperf.com/array-iteration-direction

7 个答案:

答案 0 :(得分:80)

因为你的转发条件必须每次都接收你的数组的length属性,而另一个条件只需要检查“大于零”,这是一个非常快的任务。

当你的数组长度在循环期间没有改变,并且你真的看ns-perfomance时,你可以使用

for (var i=0, l=arr.length; i<l; i++)

顺便说一句:你可以使用for (var i = arr.length; i > 0; --i)来代替for (var i = arr.length; i-- > 0; )而不是从n到1,而不是从n到1,而不是从n到1。

答案 1 :(得分:8)

因为在第一种形式中,每次迭代都会访问数组length的属性arr,而在第二种形式中,只执行一次。

答案 2 :(得分:6)

如果你想以相同的速度拥有它们,你可以为前向迭代做到这一点;

for(var i=0, c=arr.length; i<c; i++){
}

因此,您的脚本不需要在everystep上占用数组长度。

答案 3 :(得分:4)

我对此并不完全确定,但这是我的猜测:

以下代码:

for (var i = 0; i < arr.length; ++i) {;
}

在运行期间,每次循环传递后都会进行arr.length计算。当它独立时,这可能是一个微不足道的操作,但是当涉及多个/大型阵列时可能会产生影响。你能尝试以下方法:

 var numItems = arr.length;
    for(var i=0; i< numItems; ++i)
    {
    }

在上面的代码中,我们只计算一次数组长度,并使用该计算出的数字进行操作,而不是一遍又一遍地执行长度计算。

再一次,把我的想法放在这里。确实有趣的观察!

答案 4 :(得分:2)

i > 0i < arr.length快,并且在循环的每次迭代中都会发生。

你可以通过以下方式减轻差异:

for (var i = 0, len = arr.length; i < len; ++i) {;
}

这仍然不如后退项目快,但比前进选项更快。

答案 5 :(得分:1)

这些同样好:

var arr= [], L= 10000;
while(L>-1) arr[L]= L--;

OR

var arr= [], i= 0;
while(i<10001) arr[i]=i++;

答案 6 :(得分:1)

如下所示,它将以相同的方式执行。因为arr.length在前进的每次迭代中都需要时间。

int len = arr.length;

转发

for (var i = 0; i < len; ++i) {
}

<强>向后

for (var i = len; i > 0; --i) {
}