for循环中var与let的差异解析:为何var示例中i最终为4?
为什么用var的循环里setTimeout会拿到i=4?
先看两种代码的执行结果:
用let声明循环变量时:
const array = [1, 2, 3, 4]; for (let i = 0; i < array.length; i++) { setTimeout(() => { console.log(array[i]); }, 1000); }
1秒后会依次输出1, 2, 3, 4。
换成var声明循环变量时:
const array = [1, 2, 3, 4]; for (var i = 0; i < array.length; i++) { setTimeout(() => { console.log(array[i]); }, 1000); }
1秒后会输出四次undefined。
核心原因:var的作用域与异步执行的冲突
var声明的变量属于函数作用域(如果不在函数内就是全局作用域),整个for循环里的i是同一个变量——循环的每一次迭代都是在修改这个变量的值,从0一直自增到4。setTimeout是异步任务,它的回调函数不会立刻执行,要等1秒后才会被加入执行队列。而这时候for循环早就跑完了:当i自增到4时,i < array.length(也就是4<4)的条件不成立,循环终止,此时i的固定值就是4。- 等四个
setTimeout的回调依次执行时,它们访问的都是同一个全局的i,这时候i=4,而数组array的索引最大是3,array[4]不存在,所以输出undefined。
对比let的情况:let是块级作用域,循环的每一次迭代都会创建一个全新的i变量,每个setTimeout的回调捕获的都是当前迭代对应的那个i,所以1秒后能正确输出数组的对应元素。
内容的提问来源于stack exchange,提问作者M11CH
相关产品推荐
相关产品推荐

