Do loops check the array.length every time when comparing i against array.length?

前端 未结 5 1455
一向
一向 2020-11-30 07:44

I was browsing around and I found this:

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

My first thoughts are:

相关标签:
5条回答
  • 2020-11-30 07:53

    One reason to do this is say, if you're adding elements to the array during the loop but do not want to iterate over them. Say you want to turn [1, 2, 3] into [1, 2, 3, 1, 2, 3]. You could to that with:

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

    If you don't save the length before the loop, then array.length will keep increasing and the loop will run until the browser crashes / kills it.

    Other than that, as the others said, it mildly affects performance. I wouldn't make a habit out of doing this because "premature optimization is the root of all evil". Plus, if you change the size of the array during the loop, doing this could break your code. For instance, if you remove elements from the array during the loop but keep comparing i to the previous array size, then the loop will try to access elements beyond the new size.

    0 讨论(0)
  • 2020-11-30 07:58
    Is it worth it? (obviously yes, why else he will do it this way?)

    Absolutely yes. Because, as you say, loop will calculate array length each time. So this will cause an enormous overhead. Run the following code snippets in your firebug or chrome dev tool vs.

    // create an array with 50.000 items
    (function(){
        window.items = [];
        for (var i = 0; i < 50000; i++) {
            items.push(i);
        }
    })();
    
    // a profiler function that will return given function's execution time in milliseconds
    var getExecutionTime = function(fn) {
        var start = new Date().getTime();
        fn();
        var end = new Date().getTime();
        console.log(end - start);
    }
    
    var optimized = function() {
        var newItems = [];
        for (var i = 0, len = items.length; i < len; i++) {
            newItems.push(items[i]);
        }
    };
    
    
    var unOptimized = function() {
        var newItems= [];
        for (var i = 0; i < items.length; i++) {
            newItems.push(items[i]);
        }
    };
    
    getExecutionTime(optimized);
    getExecutionTime(unOptimized);
    

    Here is the approximate results in various browsers

    Browser    optimized    unOptimized
    Firefox    14           26
    Chrome     15           32
    IE9        22           40
    IE8        82           157
    IE7        76           148 
    

    So consider it again, and use optimized way :)
    Note: I tried to work this code on jsPerf but I couldn't access jsPerf now. I guess, it is down when I tried.

    0 讨论(0)
  • 2020-11-30 08:14

    I always thought in JavaScript length was just a property of the array object, pre-calculated by previous array operations - creation, addition, removal - or overridden by the user, so you're just looking up a variable anyway? I must admit I had just assumed that because of the lack of parenthesis, but looking at the MDN page for array.length, it seems to say the same thing.

    In languages where length is a method or length is calculated by a standard library function, then you should pre-calculate the length before running the loop so The array isn't calculated every iteration, particularly for large datasets. Even then, in modern high level languages like Python, len() just returns the length property of the array object anyway.

    So unless I'm mistaken, the complexity is just O(1), and from that standpoint, even if the variable were slightly faster than a property to lookup each pass, it wouldn't be worth the potential trouble of creating/reusing additional variables outside of the protective for loop scope.

    However, I suspect that in this case the reason the example's programmer chose this approach is simply just a habit they picked up in another language and carried forwards JavaScript.

    0 讨论(0)
  • 2020-11-30 08:16

    Here are a number of performance tests for different approaches

    http://www.websiteoptimization.com/speed/10/

    0 讨论(0)
  • 2020-11-30 08:17

    A loop consisting of three parts is executed as follows:

    for (A; B; C)
    
    A - Executed before the enumeration
    B - condition to test
    C - expression after each enumeration (so, not if B evaluated to false)
    

    So, yes: The .length property of an array is checked at each enumeration if it's constructed as for(var i=0; i<array.length; i++). For micro-optimisation, it's efficient to store the length of an array in a temporary variable (see also: What's the fastest way to loop through an array in JavaScript?).

    Equivalent to for (var i=0; i<array.length; i++) { ... }:

    var i = 0;
    while (i < array.length) {
        ...
        i++;
    }
    
    0 讨论(0)
提交回复
热议问题