let在for循环中每次迭代创建独立变量绑定,各闭包函数捕获对应迭代的i值,故输出0、1、2;var则共享单个变量,所有闭包均引用最终值3;初始化表达式中的函数捕获初始作用域的i,恒返回0。

关键在于:每次迭代的 let 声明变量不是复用同一个内存位置,而是新建一个绑定。这不是“复制值”,而是为每次循环创建独立的作用域层级和变量实例。
for 循环中 let 的迭代绑定机制
当写 for (let i = 0; i 时,JavaScript 引擎在每次进入循环体前,都会为 <code>i 创建一个全新的、只属于该次迭代的绑定(binding),而非共享一个变量。
- 第 1 次迭代:创建
i_0,初始化为 0,循环体中的i指向它 - 第 2 次迭代:创建
i_1,初始化为 1(来自上一轮递增后的值),循环体中的i指向它 - 第 3 次迭代:创建
i_2,初始化为 2,循环体中的i指向它
这些绑定彼此隔离,即使同名,也互不影响。
为什么闭包能记住各自的 i 值
在循环体内定义函数(如赋值给数组)时,该函数会捕获当前迭代作用域中的 i 绑定:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
a[0] = () => console.log(i)→ 捕获的是i_0 -
a[1] = () => console.log(i)→ 捕获的是i_1 -
a[2] = () => console.log(i)→ 捕获的是i_2
所以调用时输出 0、1、2 —— 因为每个函数引用的是各自迭代中那个独立的 i,不是全局或外部的某个“最终 i”。
对比 var:没有迭代绑定,只有单个变量
用 var i = 0 时,整个 for 循环共用一个 i 变量:
- 所有循环体内的函数都闭包引用这同一个
i - 循环结束时
i === 3,所有函数执行时读到的都是这个最终值 - 不存在“每次迭代的新变量”,只有变量提升 + 函数作用域复用
注意:初始化表达式里的函数仍捕获初始绑定
像 for (let i = 0, getI = () => i; ...) 这种写法中,getI 是在循环开始前就创建的,它捕获的是最外层初始化作用域的 i(即初始值 0),而不是每次迭代的新 i。因此 getI() 总返回 0 —— 这是初始化阶段与迭代阶段作用域分离导致的,不是 bug,而是规范行为。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










