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

JavaScript事件循环中for循环搭配setTimeout时var与let输出差异疑问

输出差异原因分析

1 前置基础:setTimeout的异步执行规则

JavaScript的事件循环机制中,setTimeout属于异步宏任务,即便延迟参数设为0,其回调函数也不会在当前同步上下文执行,必须等所有同步代码(此处即整个for循环)执行完毕后,才会进入任务队列依次调度执行。
也就是说:所有setTimeout的回调触发时,for循环已经完全执行结束。

2 var声明的变量特性导致输出全为5

  • var没有块级作用域,仅支持函数/全局作用域,在for循环头部用var声明的变量i,整个循环过程中只会创建唯一的一个全局/函数作用域变量
  • 所有setTimeout的回调函数引用的都是同一个i变量,for循环执行结束后i的值已经自增到5,因此所有回调执行时打印的都是最终的i值5

3 let声明的变量特性导致输出0-4

  • let是ES6新增的支持块级作用域的声明关键字,在for循环头部用let声明变量i时,有特殊的作用域绑定规则:每一轮循环都会创建一个独立的块级作用域,并且将当前轮次的i值绑定到这个作用域中,每一轮的i都是互不干扰的独立变量
  • 每个setTimeout的回调函数引用的都是当前循环轮次对应的独立i变量,因此回调执行时可以正确打印对应轮次的i值0到4

补充:var场景下实现同等输出的方案

如果要使用var也得到0-4的输出,可以通过立即执行函数(IIFE)手动创建独立作用域存储每轮的i值,等效于let的块级作用域效果:

for (var i = 0; i < 5; i++) {
  // 立即执行函数接收当前i值作为参数,创建独立作用域存储
  (function(curI) {
    setTimeout(() => {
      console.log("var keyword output : ", curI);
    }, 0);
  })(i)
}

内容的提问来源于stack exchange,提问作者faizan zafer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 21:36:02