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

bsr*_*bsr 5 javascript nested-loops

我记得变量是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++) {
                ...
            }
        }
Run Code Online (Sandbox Code Playgroud)

Jam*_*ice 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++) {

    }
}
Run Code Online (Sandbox Code Playgroud)

至于这部分:

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

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

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

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

  • DN标识符d.
  • varAlreadyDeclared是调用env的 HasBinding具体方法传递dn作为参数的结果.
  • 如果varAlreadyDeclared为false,则
    • 调用env的 CreateMutableBinding具体方法,将dnconfigurableBindings作为参数传递.
    • 调用env的 SetMutableBinding具体方法,将dn,undefined和strict作为参数传递.

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