我试图从MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
中澄清这一陈述背后的含义上面的例子按预期工作,因为它的五个实例 (匿名)内部函数指的是五个不同的实例 变量i。
假设for循环初始化表达式使用let
关键字。表达式是否在每次迭代时重新声明(即,有一个新范围)?例如,
var func;
for (let i = 0; i < 5; i++) {
if (i == 1) {
func = () => i
}
if (i == 4) {
i = 100
}
}
console.log(func()) // output is 1
func()
的输出即使在{for循环结束时1
也是i == 4
。这似乎表明i
中的func
来自i == 1
的范围,即使i
在最后一次迭代中设置为100
。
将其与下面的i
在for循环块之外声明的情况进行比较。
if (true) {
var func;
let i = 0
for (i = 0; i < 5; i++) {
if (i == 1) {
func = () => i
}
if (i == 4) {
i = 999
}
}
}
console.log(func()) // output is 999
在这种情况下,似乎有一个i
实例在最后一次迭代中得到更新(但没有重新声明)。
那么,使用let
是否会导致for循环创建一个新的块作用域,并为每次迭代创建一个init变量的新声明?
答案 0 :(得分:0)
let
声明的变量的作用域位于最近的块中。
http://exploringjs.com/es6/ch_core-features.html#sec_from-var-to-const
在ES6中,您还可以通过let和const声明变量。这些变量是块范围的,它们的范围是最里面的封闭块。 let大致是var。
的块范围版本
这意味着您的代码应该与此相同:
var func;
for (var i = 0; i < 5; i++) {
(function (j) {
if (j == 1) {
func = () => j
}
if (j == 4) {
j = 100
}
})(i);
}
console.log(func()) // output is 1
答案 1 :(得分:0)
第13.7.4.9 of the ECMAScript spec节似乎表明zer00ne提到的是真的:
i
的新绑定iii让lastValue为lastIterationEnv.GetBindingValue(bn,true)。
诉执行thisIterationEnv.InitializeBinding(bn,lastValue)。
在循环内声明的函数将在特定于迭代的绑定上形成一个闭包 - 所以有效地,你将为循环的每次迭代获得一个不同的闭包。