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

为什么var和let在setTimeout中会输出不同的结果?

核心原因是你对let在for循环中的绑定规则存在认知误区:for循环头部用let声明迭代变量时,不会复用同一个变量,而是每次迭代都会创建一个全新的独立块级绑定,这是ES6规范专门针对这类场景做的特殊设计。

以下是三段代码的具体运行逻辑:

  • var 声明场景
    var没有块级作用域,整个循环中声明的i实际挂载在外部作用域(全局作用域或者外层函数作用域),所有setTimeout回调通过闭包引用的都是同一个i变量。等1000ms后回调执行时,for循环早已执行完毕,i已经被累加为最终值3,因此所有输出都是3。

  • let 声明场景
    按照ES6规范,for (let i = 0; i < array.length; i++)的写法中,每次循环都会生成一个新的、独立的i绑定,值为当前迭代的数值。每个setTimeout回调捕获的是当前轮次的独立i变量,因此2000ms后回调执行时,各自拿到的就是对应迭代轮次的0、1、2、3,最终输出递增数字。
    如果要在ES5没有let的环境下实现同样效果,需要用立即执行函数(IIFE)手动创建独立作用域存储当前轮次的i,本质和let的自动绑定逻辑一致:

for (var i = 0; i < array.length; i++) {
  // 每次迭代创建独立作用域存当前的i值
  (function(curI) {
    setTimeout(function(){
      console.log('var index' + curI);
    }, 1000)
  })(i)
}
  • const 声明场景
    const声明的变量禁止重新赋值,第一次迭代i=0可以正常初始化,但到下一轮迭代要执行i++操作时,相当于尝试修改常量的值,会直接抛出TypeError,因此不需要等setTimeout执行,循环第一次结束就会报错。

内容的提问来源于stack exchange,提问作者Don P

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:39:03