4

正如我的研究让我相信 for 循环是 javascript 语言中最快的迭代结构。我在想,为 for 循环声明一个条件长度值会更快……为了更清楚,您认为以下哪个更快?

示例一

for(var i = 0; i < myLargeArray.length; i++ ) {
    console.log(myLargeArray[i]);
} 

示例二

var count = myLargeArray.length;
for(var i = 0; i < count; i++ ) {
    console.log(myLargeArray[i]);
} 

我的逻辑是,在示例中的每次迭代中,在每次迭代中访问 myLargeArray 的长度比访问示例二中的简单整数值的计算成本更高?

4

5 回答 5

7

与下面的一些陈述相反,数组的长度不是在每次迭代时计算的。Array 的长度是一个属性,通过修改pop, push, shift,unshift等操作来设置splice

不过,您会看到性能受到轻微影响,因为属性查找的成本高于局部变量。因此缓存长度是一个好主意。但是,除非您处理庞大的数据集,否则您不会看到很大的不同。

但是有一种特殊情况,确实在每次迭代中都计算了长度。HTML 节点集合就是这种情况。由于这些是活动对象,因此长度不是数组意义上的属性。如果你这样做:

for (var i=0; i < collection.length; i++) {
    collection[i]
};

然后在每次迭代时解析集合。

至于优化 for 循环,我通常使用以下技术进行缓存:

// if order is of no concern, just iterate from length-1 to 0
for (var i = arr.length - 1; i >= 0; i--){
    arr[i]
};

// use the for loop statement to set up scoped variables
for (var i=0, length = arr.length; i < length; i++) {
    // do something
}
于 2012-10-09T09:45:41.337 回答
4

来自JavaScript Garden,一个关于 JavaScript 怪癖的好资源。

尽管长度属性是在数组本身上定义的,但在循环的每次迭代中进行查找仍然存在开销。虽然最近的 JavaScript 引擎可能会在这种情况下应用优化,但无法判断代码是否会在这些较新的引擎之一上运行。

于 2012-10-09T09:35:55.687 回答
1

我认为每次都使用第二个版本不会有任何损失,尽管如果数组长度实际上每次都是从头开始计算的,除非数组实际上被循环突变,否则我会感到惊讶。

不要忘记你可以在第一部分声明多个变量for

for(var i = 0, count = myLargeArray.length; i < count; i++ ) {
    console.log(myLargeArray[i]);
}
于 2012-10-09T09:33:21.503 回答
1

来自 高性能 JavaScript

减少每次迭代的工作量:

//original loops
for (var i=0; i < items.length; i++){
process(items[i]);
}

var j=0;
while (j < items.length){
process(items[j++]]);
}

var k=0;
do {
process(items[k++]);
} while (k < items.length);



//minimizing property lookups
for (var i=0, len=items.length; i < len; i++){
process(items[i]);
}

var j=0,
count = items.length;
while (j < count){
process(items[j++]]);
}

var k=0,
num = items.length;
do {
process(items[k++]);
} while (k < num);


//minimizing property lookups and reversing
for (var i=items.length; i--; ){
process(items[i]);
}

var j = items.length;
while (j--){
process(items[j]]);
}

var k = items.length-1;
do {
process(items[k]);
} while (k--);

减少迭代次数:

//credit: Jeff Greenberg
var i = items.length % 8;
while(i){
process(items[i--]);
}
i = Math.floor(items.length / 8);
while(i){
process(items[i--]);
process(items[i--]);
process(items[i--]);
process(items[i--]);
process(items[i--]);
process(items[i--]);
process(items[i--]);
process(items[i--]);
}

请参阅JavaScript 优化

于 2012-10-09T10:33:37.780 回答
0

是的,您是对的 myLargeArray.length 正在循环的每次迭代中计算(第一个示例)。链接1 链接 2

for(var i = 0; i < myLargeArray.length; i++ ) {
    console.log(myLargeArray[i]); 
} 
于 2012-10-09T09:31:06.870 回答