7

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

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

3 回答 3

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 循环在一次迭代后终止

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

如果您对内部工作的真正解释感兴趣,ECMAScript 规范(声明绑定实例化)详细介绍了它。总而言之,每次控制进入一个新的执行上下文时,都会发生以下情况(比这发生的要多得多,但这是其中的一部分):

对于代码中的每个VariableDeclarationVariableDeclarationNoIn d,按源文本顺序执行

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

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

于 2012-09-25T12:57:29.847 回答
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范围和提升

于 2012-09-25T12:57:05.930 回答
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'
于 2012-09-25T13:46:54.523 回答