Javascript - 嵌套for循环索引的范围

时间:2012-09-25 12:54:29

标签: javascript nested-loops

我记得变量是Javascript中的函数作用域。但是,如果我在循环中重新定义局部变量,行为如何。一个常见的用例是嵌套循环。  在下面的代码中,如果我将j更改为i,则外部for循环在一次迭代后终止,因为外部作用域中的i值与inner for循环相同。由于我使用var,我期待(类似于其他语言)它在内部fo循环中被重新定义。这是否意味着在JS中,没有办法在函数范围内重新声明和使用局部变量。

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

3 个答案:

答案 0 :(得分:8)

正如你所说,JavaScript只有功能范围。变量声明被提升到声明它们的作用域的顶部。您的示例解释如下:

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++) {

    }
}

至于这一部分:

  

如果我将j更改为i,则外部for循环在一次迭代后终止

如果将j替换为i,则在内循环的第一次迭代后,i将为y.length - 1,外循环将继续或停止,取决于x.lengthy.length之间的差异。

如果您对内部运作的真实解释感兴趣,ECMAScript spec (Declaration Binding Instantiation)会详细介绍它。总而言之,每次控件进入新的执行上下文时,都会发生以下情况(比这更多,但这是其中的一部分):

  

对于代码中的每个 VariableDeclaration VariableDeclarationNoIn d ,   源文本顺序

     
      
  • dn 成为 d 中的标识符
  •   
  • varAlreadyDeclared 成为调用 env的 HasBinding具体的结果   传递 dn 作为参数的方法。
  •   
  • 如果 varAlreadyDeclared 为false,则   
        
    • 调用 env的 CreateMutableBinding传递 dn 的具体方法    configurableBindings 作为参数。
    •   
    • 调用 env的 SetMutableBinding   具体方法传递 dn ,undefined和 strict 作为参数。
    •   
  •   

这意味着如果每个执行上下文多次声明一个变量,它将被有效地忽略。

答案 1 :(得分:4)

每个var声明都会放在当前范围的顶部,因此您的代码与以下内容相同:

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

请检查:JavaScript Scoping and Hoisting

答案 2 :(得分:0)

JS中没有块级范围。

但是,如果最需要在代码中声明/重新声明相同的变量名称,则可以执行以下操作:

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

并使用它:

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);
    });
});

这将给我们带来以下结果:

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'