在具有多个循环的函数中使用 var?

Kor*_*gay 2 javascript var let

引自《JavaScript: The Definitive Guide》一书

与用let声明的变量不同,用 多次声明同一个变量是合法的var。并且由于var变量具有函数作用域而不是块作用域,因此进行这种重新声明实际上很常见。该变量i经常用于整数值,特别是作为 for 循环的索引变量。在具有多个 for 循环的函数中,通常每个循环都开始for(var i = 0;......因为var这些变量的范围不限于循环体,所以这些循环中的每一个都(无害地)重新声明和重新初始化相同的变量。

我无法理解这一段的意思。首先,我假设以下不会与不迭代的第二个循环一起工作,因为i将是函数作用域:

(function foo() {
    for (let i = 0; i < 2; i++) {
        console.log(i);
    }
    for (let i = 0; i < 2; i++) {
        console.log(i);
    }
})();
Run Code Online (Sandbox Code Playgroud)

但它打印

0
1
0
1
Run Code Online (Sandbox Code Playgroud)

然后我假设这会打印0 0 1 1 0 1,但事实并非如此:

0
1
0
1
Run Code Online (Sandbox Code Playgroud)

有人能帮我理解什么意思吗

在多个for循环的函数中,var可以在每个循环中无害地使用

和它有什么不同let

对我来说,它看起来正好相反(这也很令人困惑)let可以在具有多个循环的函数中无害地使用:

(function foo() {
    for (var i = 0; i < 2; i++) {
        console.log(i);
        for (var i = 0; i < 2; i++) {
            console.log(i);
        }
    }
})();
Run Code Online (Sandbox Code Playgroud)

印刷:

0
0
1
1
0
1
Run Code Online (Sandbox Code Playgroud)

Cer*_*nce 5

let禁止在同一作用域内重新声明变量,如下所示:

let foo = 10;
let foo = 20;
Run Code Online (Sandbox Code Playgroud)

var 但是,变量可以是:

var foo = 10;
var foo = 20;
console.log('ok');
Run Code Online (Sandbox Code Playgroud)

在你的第一个片段中,letfor循环头中声明的变量只存在于循环内;它们是块作用域的,而不是外部块或函数的作用域:

(function foo() {
    for (let i = 0; i < 2; i++) {
        // console.log(i);
    }
    for (let i = 0; i < 2; i++) {
        // console.log(i);
    }
    // doesn't exist out here:
    console.log(i);
})();
Run Code Online (Sandbox Code Playgroud)

let iS上方建立i以s两个不同的领域,这就是为什么它没有被禁止。相似地:

(function foo() {
    {
        let i = 10;
    }
    {
        let i = 20;
    }
    console.log('OK up until here');
    // doesn't exist out here:
    console.log(i);
})();
Run Code Online (Sandbox Code Playgroud)

vars,相比之下,具有函数作用域,而不是块作用域——使用您var的循环版本,因为只有一个函数,这个:

(function foo() {
    for (var i = 0; i < 2; i++) {
        console.log(i);
        for (var i = 0; i < 2; i++) {
            console.log(i);
        }
    }
})();
Run Code Online (Sandbox Code Playgroud)

相当于

(function foo() {
    var i; // the `i` variable exists at this level
    for (i = 0; i < 2; i++) {
        console.log(i);
        for (i = 0; i < 2; i++) {
            console.log(i);
        }
    }
})();
Run Code Online (Sandbox Code Playgroud)

然后我假设这会打印 0 0 1 1 0 1,但事实并非如此:

i 在每个循环开始时被初始化为零。

第一个循环在函数开始时开始一次。

第二个循环在 logging 之后开始i,在外循环的每次迭代中。

(function foo() {
    for (var i = 0; i < 2; i++) {
        console.log(i);
        for (var i = 0; i < 2; i++) {
            console.log(i);
        }
    }
})();
Run Code Online (Sandbox Code Playgroud)
  • 外循环初始化:0 分配给 i
  • 0 被记录
  • 内循环初始化:0 分配给 i
  • 0 被记录
  • 内循环将 i 增加到 1 并重新开始
  • 内循环:1 被记录
  • 内循环将 i 增加到 2 并中断,因为 i < 2 不再满足
  • 外循环将 i 增加到 3 并中断,因为不再满足 i < 2

所以你被0 0 1登录了。

这篇文章大概是什么意思

在多个 for 循环的函数中,var 可以在每个循环中无害地使用

是如果两个循环都在函数的同一级别上,它就可以工作,例如

for (...) {
}
for (...) {
}
Run Code Online (Sandbox Code Playgroud)

如果两个循环都使用相同的变量,它肯定不适用于嵌套循环,因为只有一个i变量,而不是每个循环一个。

其中 let 可以在具有多个循环的函数中无害地使用:

对于嵌套循环,是的,因为声明的变量let对于每个循环都是唯一的,而不是在整个包含函数中共享。