You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript循环初始化变量的作用域?为何两段代码输出不同?

问题解答:循环变量作用域与闭包的影响

好问题!这其实涉及到JavaScript中let的块级作用域特性,以及闭包对变量绑定的捕获逻辑,咱们一步步拆解来看:

1. 循环初始化语句中let定义变量的作用域

当你在for循环的初始化部分(也就是for(...)的第一个括号里)用let定义变量时,这个变量的作用域是每一次单独的循环迭代块。而且JavaScript引擎会在每次循环迭代时,自动创建一个新的变量绑定——换句话说,每次循环里的i都是一个全新的变量,只是名字相同罢了,它们各自独立,不会互相干扰。

2. 两段代码输出差异的原因

咱们分别看两段代码的逻辑:

第一段代码:输出 0 1 2 3 4

let nodes = [];
for (let i = 0; i < 5; ++i) {
  nodes[i] = () => i;
}
for (let node of nodes) {
  console.log(node());
}

这里的let i是在循环初始化里定义的,每次迭代都会生成一个新的i变量。你添加到nodes数组里的每个箭头函数,都会捕获当前这次迭代对应的那个i的绑定。当后续调用这些箭头函数时,每个函数都能找到自己对应的i的值(也就是迭代时的0、1、2、3、4),所以输出就是依次递增的数字。

第二段代码:输出 5 5 5 5 5

let nodes = [];
let i;
for (i = 0; i < 5; ++i) {
  nodes[i] = () => i;
}
for (let node of nodes) {
  console.log(node());
}

这段代码里的i是在循环外部定义的,整个循环过程中只有同一个i变量在被反复更新。箭头函数不会捕获当时的i值,而是捕获i的变量绑定——也就是说,所有箭头函数都指向同一个i。当循环结束时,i已经完成了最后一次递增,值变成了5,所以不管调用哪个箭头函数,它们返回的都是这个已经变成5的i,最终输出全是5。

简单总结一下:核心差异在于变量的作用域和绑定方式——循环内的let会为每个迭代创建独立变量,而外部定义的变量是全局共享的,箭头函数捕获的是变量的绑定而非临时值。

内容的提问来源于stack exchange,提问作者Bimo Adityarahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 21:38:14