什么';在javascript中迭代项目的最佳方式是什么?

什么';在javascript中迭代项目的最佳方式是什么?,javascript,for-loop,undefined,Javascript,For Loop,Undefined,我最近在Javascript中使用了一种不同的数组循环方式 我曾经写过这样的循环: for (var len = 0; len < testData.length; len++) { total = total + testData[len]; } 我想知道这些会有怎样的表现,所以我经常去发现它。结果非常惊人。我希望第二种方法比第一种快一点,但实际上要快得多 这里有没有我不知道的地方?或者这是循环浏览列表项的最佳方式 更新: gray state即将到来,并向我指出了测试用例中的一个

我最近在Javascript中使用了一种不同的数组循环方式

我曾经写过这样的循环:

for (var len = 0; len < testData.length; len++) {
  total = total + testData[len];
}
我想知道这些会有怎样的表现,所以我经常去发现它。结果非常惊人。我希望第二种方法比第一种快一点,但实际上要快得多

这里有没有我不知道的地方?或者这是循环浏览列表项的最佳方式

更新:

gray state即将到来,并向我指出了测试用例中的一个简单缺陷,它使得测试速度似乎更快

纠正错误后,这是最快的:

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

我认为第一种形式更好。第二种形式有一些问题。如果您有一个包含
falsy
值的稀疏数组,该怎么办?比如:
var testData=[“text”,未定义,false,0,5]

我还希望第一种形式的表现更好。特别是如果您“缓存”了
testData.length的值,如下所示:

var i, len = testData.length;
for (i = 0; i < len; i += 1) {
  total = total + testData[i];
}
var i,len=testData.length;
对于(i=0;i
关于性能,
testData[len]
只是检查元素是否已定义且不为null/false/“falsish”,这比比较快,尤其是每次迭代检索testData.length

因此,第二种方法更快,但并不更可靠——正如弗里茨·范·坎本(Frits van Campen)所正确指出的那样。


更新:我错了,
forEach
非常慢!看来循环更好


您应该使用ECMAScript第5版中定义的
forEach

testData.forEach(function(val,i,arr){
    total += val;
});
理由如下:

  • val
    是当前值
  • i
    是当前索引
  • arr
    是数组
您不必全部使用它们:

testData.forEach(function(val){
    total += val;
});
对于不支持它的浏览器,可以使用此垫片:

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);
        }
    }
}
if(!Array.prototype.forEach){
Array.prototype.forEach=函数(fn,范围){
对于(变量i=0,len=this.length;i

有关更多信息,请参阅。

您也可以执行如下循环:

var i = testData.length;

while (i--){
    console.log(testData[i]);
}
请注意,它向后遍历数组

或者,总结一下:

var i = testData.length, sum=0;

while (i--){
    sum += testData[i];
}

设置代码插入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=[];
对于(变量i=0;i<1000;i++){
testData.push(i);//将0推送到`testData`
}
对于(var len=0;testData[len];len++){//在第一个条件检查时循环中断,因为testData[0]为0。
总计=总计+测试数据[len];
}
按如下所示更改设置代码,并查看差异

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

根据Shmidt的回答,可以使用反向循环。在Firefox和Chrome上,它的速度似乎比以前快了一点:

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

Test:

缓存变量的好主意,但我仍然认为简单的null/falsish检查,因为testData[len]更快+1用于注释falsy值。为了避免上述问题,可以使用条件(testData[len]!=void 0)。这对于所有定义的值都是正确的。@Paritossing的问题是
undefined===void 0
仍然是正确的。@Paritossing:您可以使用
undefined
值定义属性。但除此之外,如果要进行这样的比较,那么最好将索引与长度进行比较。缓存长度确实有助于提高速度。如果要向变量添加值,应使用
+=
而不是重复变量。当您说“最佳”时,您在寻找什么?速度、代码可读性、可靠性?你在循环什么类型的数组?如果
testData
中存在错误值,那么第二个循环将提前停止。这可能是您看到的“性能提升”的一部分,但您的JSPerf测试存在很大缺陷。由于
0
值,它在第一次迭代时停止,因此速度似乎很快。将初始化更改为从
1
开始,而不是从
0
开始,然后进行比较<代码>用于(变量i=1;i<1000;i++){
Corrected JSPerf test显示了一个非常不同的结果。我完全忘记了forEach。我将它添加到JSPerf中。虽然这是一个明显的解决方案,但它却是迭代速度最慢的方法。@Sorskot怪异…我认为它应该更快,因为它是本机代码。可能是因为它需要一个函数,所以作用域链会增长。Curiosly我正在使用
forEach
启动一个项目,我将把它改为一个循环,感谢您的jsperfcomparison@Oriol:它与作用域链无关;作用域在JavaScript中是静态的。
forEach
的问题是函数调用不是免费的——事实上,正如您所看到的,它非常昂贵。我将它添加到了stcase。令人惊讶的是,常规for循环速度更快。它似乎非常接近。我曾尝试过其他一些浏览器,在某些浏览器中,这种方式实际上是最快的…这些测试用例使用长度为1000的数组运行。如果列表显著缩短,则测试结果会发生变化。我无法解释这些性能结果中的任何一个。可能是因为varyi在每个javascript引擎中进行优化。
var testData = [];
for (var i = 0; i < 1000; i++) {
  testData.push(i+1);
}
var total = 0;
for (var len = testData.length-1; len >=0; len--) {
  total += testData[len];
}