for (var i = 0; i < 5; ++i) { setTimeout(() => console.log(i), 0) } // 你可能以为会输出0、1、2、3、4 // 实际上会输出5、5、5、5、5
之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。在之后执行超时逻辑时,所有的i都是同一个变量,因而输出的都是同一个最终值。
而使用let声明迭代变量时,JavaScript引擎在后台会为每个迭代循环声明一个新的迭代变量。每个setTimeout引用的都是不同的变量实例,所以console.log输出的是我们期望的值,也就是循环执行过程中每个迭代变量的值。
for (let i = 0; i < 5; ++i) { setTimeout(() => console.log(i), 0) } // 会输出0、1、2、3、4