for循环的初始化,条件和事后思考在JavaScript中是如何工作的?



我已经阅读了MDN文档,我真的可以说这是我第一次在一段时间内感到困惑。

参考以下代码:

for (
let i = 0, getI = () => i, incrementI = () => i++;
getI() < 3;
incrementI()
) {
console.log(i);
}
// Logs 0, 0, 0

我看到第一次迭代:

  • for循环将i初始化为0
  • 创建i
  • 的闭包
  • 创建i++
  • 的闭包
  • 调用getI函数并返回0,执行继续条件,循环执行console.log(i)
    • 是否在console.log(i)之后创建了新的词法作用域?初始的i变量消失了吗?
    • getI函数得到定义为每个新的迭代?
  • 调用incrementI,执行i++
    • 是一个新的i变量创建,以前的i复制到新的i,然后新的i增加?
  • 下一次迭代开始
    • 如果生成了一个新的i,并且增加了新的值,为什么console.log(i)仍然指向初始的i,即0?

我在MDN中阅读了关于for的文档,但是我找不到代码片段中显示的行为的解释。为什么记录0,0,0而不是0,1,2?

答案就在文档的这一部分

初始化块的作用域效应可以理解为声明发生在循环体中,但恰好在条件和事后考虑部分中可访问。更准确地说,let声明是for循环的特殊情况-如果初始化是let声明,则每次在循环体求值后,都会发生以下情况:

  • 使用新的let声明的变量创建新的词法作用域。
  • 使用上次迭代的绑定值来重新初始化新变量。
  • 事后在新范围内评估。

例如,在循环的每次迭代之后,用前一个的值声明一个新的i。然后对afterthought求值。但是,在您的情况下,getIincrementI原始i上关闭,原始i被增加并检查(因此循环最终停止),但下一次调用console.log总是使用"new"i,它被初始化为0(即在之前的前一个迭代的值被计算),然后永远不会增加。

如果你想让这个函数工作,只需将i的初始化放在for之外。

let i;
for (
i = 0, getI = () => i, incrementI = () => i++;
getI() < 3;
incrementI()
) {
console.log(i);
}

相关内容

  • 没有找到相关文章

最新更新