Javascript - scope of nested for loop index

后端 未结 3 1662
一向
一向 2021-01-05 19:03

I remember variables are function scoped in Javascript. But, how is the behavior if I redefine the local variable in a loop. One common use case is nested loops. In the bel

相关标签:
3条回答
  • 2021-01-05 19:17

    Every var declarement will be put into the top of the current scope, so your code is same as:

       var i, j, len;
       for (i = 0, len = x.length; i < len; i++) {
            ...
            for (j = 0, len = y.length; j < len; j++) {
                ...
            }
        }
    

    Check this: JavaScript Scoping and Hoisting

    0 讨论(0)
  • 2021-01-05 19:27

    There's no block level scope in JS.

    But if it's utmost necessary to have/re-declare the same variable name in your code, you can do:

    function loopIt(arr, fn, scope) {
        for (var i = 0, len = arr.length; i < len; i++) {
            fn.call(scope || this, arr[i], i, arr);
        }
    }
    

    And use it like:

    var firstArr = ["a", "b"];
    var secondArr = ["c", "d"];
    
    loopIt(firstArr, function(item, i) {
        var msg = "Hey it's '" + item + "'";
        console.log(msg);
    
        // if you want access to the parent scope's var
        var scopedItem = item;
    
        loopIt(secondArr, function(item, i) {
            var msg = "Hello it's '" + item + "' in '" scopedItem + "'";
            console.log(msg);
        });
    });
    

    That will give us results of:

    Hey it's 'a'
    Hello it's 'c' in 'a'
    Hello it's 'd' in 'a'
    Hey it's 'b'
    Hello it's 'c' in 'b'
    Hello it's 'd' in 'b'
    
    0 讨论(0)
  • 2021-01-05 19:29

    As you said, JavaScript only has function scope. Variable declarations are hoisted to the top of the scope in which they are declared. Your example is interpreted like this:

    var i, j, len; //Declarations are hoisted...
    for (i = 0, len = x.length; i < len; i++) { //Assignments happen in place
        for (j = 0, len = y.length; j < len; j++) {
    
        }
    }
    

    As for this part:

    if I change j to i, the outer for loop terminates after one iteration

    If you replace j with i, then after the first iteration of the inner loop, i will be y.length - 1, and the outer loop will either continue or stop, depending on the difference between x.length and y.length.

    If you're interested in the real explanation of the internal workings, the ECMAScript spec (Declaration Binding Instantiation) covers it in detail. To summarise, every time control enters a new execution context, the following happens (a lot more than this happens, but this is part of it):

    For each VariableDeclaration and VariableDeclarationNoIn d in code, in source text order do

    • Let dn be the Identifier in d.
    • Let varAlreadyDeclared be the result of calling env’s HasBinding concrete method passing dn as the argument.
    • If varAlreadyDeclared is false, then
      • Call env’s CreateMutableBinding concrete method passing dn and configurableBindings as the arguments.
      • Call env’s SetMutableBinding concrete method passing dn, undefined, and strict as the arguments.

    This means that if you declare a variable more than once per execution context, it will effectively be ignored.

    0 讨论(0)
提交回复
热议问题