【问题标题】:FOR loop performance in Javascript [duplicate]Javascript中的FOR循环性能[重复]
【发布时间】:2012-09-29 14:22:12
【问题描述】:

我的研究让我相信 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 的长度比访问示例二中的简单整数值的计算成本更高?

【问题讨论】:

  • 你试过写性能测试吗?
  • 不,围绕这样的测试及其参数总是有很多争议......
  • 你基本上是自己回答的。它很大程度上取决于条件,因此基本上无法测试。你提供了一个具体的例子,你可以实际测试这个具体的例子。

标签: javascript performance node.js loops for-loop


【解决方案1】:

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

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

虽然有一种特殊情况,但确实在每次迭代时都会计算长度。 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
}

【讨论】:

    【解决方案2】:

    来自JavaScript Garden,这是关于 JavaScript 怪癖的绝佳资源。

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

    【讨论】:

    • 我刚刚在 chrome 中做了一个快速的脏测试,两个循环的结果完全相同,即上面的确切代码,考虑到 myLargeArray 的长度为 1000 个元素
    【解决方案3】:

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

    别忘了你可以在for的第一部分声明多个变量:

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

    【讨论】:

    • +1 用于在初始化语句中声明两个变量
    【解决方案4】:

    来自High Performance 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 Optimization

    【讨论】:

    • 如果顺序不重要,只需提一下“//最小化属性查找和反转”方法就可以了
    【解决方案5】:

    是的,您是对的 myLargeArray.length 在循环的每次迭代中都在计算(第一个示例)。 link1link2

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

    【讨论】:

    • 查找时不计算注释长度,添加或删除项目时会更改(只是增加或减少),因此这不是OP的性能差异。
    • @Dykam 我认为读取数组的长度然后进行比较比直接与整数进行比较更具计算性。
    • 你的答案改变了。在它是关于计算数组的长度之前。我的评论现在无关紧要了。
    • @Dykam 抱歉,我必须删除它,因为由于 Array.pop();
    猜你喜欢
    • 1970-01-01
    • 2012-11-18
    • 2017-09-19
    • 2013-09-09
    • 2018-01-20
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 2016-05-03
    相关资源
    最近更新 更多