12

I recently came accross a different way of looping though an array in Javascript.

I used to write loops something like this:

for (var len = 0; len < testData.length; len++) {
  total = total + testData[len];
}

I read some code that did it this way:

for (var len = 0; testData[len]; len++) {
  total = total + testData[len];
}

I was wondering how these would perform so I used jsPerf to find it out. The results are pretty amazing. I expected the second method to be a bit it faster than the first, but it's actually much, much faster.

Is there a down side I'm missing here? Or is this the best way to loop through the items of a list.

Update:

gray state is coming and Diode pointed me to a simple flaw in the testcase which made is seem to be faster.

After correcting the mistake, this is the fastest:

var datalen = testData.length;
for (var len = 0; len <datalen; len++) {
     total = total + testData[len];
}

Update 2:

After testing in some more browsers this testcase takes a different direction again. Only in Chrome and Opera the normal for loop is the fastest. In other all other browsers Shmiddty's way is just a bit faster.

var i = testData.length, sum=0;
while (i--){
    sum += testData[i];
}
4

6 回答 6

13

我认为第一种形式更好。第二种形式有一些问题。如果你有一个包含falsy值的稀疏数组怎么办?喜欢:var testData = [ "text", undefined, false, 0, 5 ];

我也希望第一种形式表现更好。特别是如果您“缓存” testData.lengthLike 的值:

var i, len = testData.length;
for (i = 0; i < len; i += 1) {
  total = total + testData[i];
}
于 2012-09-10T18:32:02.500 回答
4


UPDATE:我错了,forEach很慢!似乎循环更好


您应该使用forEachECMAScript 第 5 版中定义的 。

testData.forEach(function(val,i,arr){
    total += val;
});

论据是:

  • val是当前值
  • i是当前索引
  • arr是数组

您不必全部使用它们:

testData.forEach(function(val){
    total += val;
});

对于不支持它的浏览器,可以使用这个 shim:

if(!Array.prototype.forEach){
    Array.prototype.forEach = function(fn, scope) {
        for(var i = 0, len = this.length; i < len; ++i) {
            fn.call(scope || this, this[i], i, this);
        }
    }
}

有关详细信息,请参阅Array.forEach

于 2012-09-10T18:34:22.707 回答
3

您也可以像这样执行循环:

var i = testData.length;

while (i--){
    console.log(testData[i]);
}

请注意,它向后遍历数组。

或者,总结一下:

var i = testData.length, sum=0;

while (i--){
    sum += testData[i];
}
于 2012-09-10T18:48:31.143 回答
2

根据 Shmiddt 的回答,您可以向后使用循环。似乎它在 Firefox 上比倒退快一点,在 Chrome 上它们并列:

var total = 0;
for (var len = testData.length-1; len >=0; len--) {
  total += testData[len];
}

测试:http: //jsperf.com/for-until-length-vs-until-undefined/10

于 2012-09-10T19:32:12.883 回答
1

关于性能,testData[len]只需检查元素是否已定义而不是 null/false/“falsish”,这比比较要快,尤其是每次迭代都检索 testData.length。

所以第二种方法更快,但不是更可靠——正如 Frits van Campen 所说的那样。

于 2012-09-10T18:34:03.177 回答
1

您的设置代码插入 0 导致循环在第一个条件下中断

var testData = [];
for (var i = 0; i < 1000; i++) {
  testData.push(i);  // pushes 0 to `testData`
}


for (var len = 0; testData[len]; len++) {   // loop breaks on first condition-check as testData[0] is 0.
  total = total + testData[len];
}

如下所示更改设置代码并查看差异

var testData = [];
for (var i = 0; i < 1000; i++) {
  testData.push(i+1);
}

http://jsperf.com/for-until-length-vs-until-undefined/6

于 2012-09-10T18:49:24.657 回答