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

为何这段代码重复输出10?TypeScript官方示例疑问求解

为什么这段TypeScript代码会重复输出10?

嘿,这个问题其实是JavaScript/TypeScript里经典的闭包陷阱,我当初刚学的时候也踩过一模一样的坑!先把你说的那段典型代码贴出来(应该就是下面这段吧?):

for (var i = 0; i < 10; i++) {
  setTimeout(() => {
    console.log(i);
  }, 100);
}

为什么会输出10次10?

说白了,问题出在var的作用域特性和异步执行的结合上:

  • var声明的变量是函数级作用域,不是块级作用域。整个循环里只有一个i变量,所有的setTimeout回调函数都共享这同一个变量。
  • setTimeout是异步执行的,它的回调会等当前同步代码(也就是整个循环)跑完之后才会执行。当所有回调开始执行时,循环已经结束了,i的值已经变成了10,所以每个回调打印的都是这个最终值。

解决办法

有几种常见的方式可以修复这个问题,按推荐程度排序:

1. 用let代替var(最省心的现代方案)

let是ES6引入的,它支持块级作用域。每次循环迭代时,都会创建一个新的i变量,每个setTimeout回调捕获的都是当前迭代的那个独立的i值:

for (let i = 0; i < 10; i++) {
  setTimeout(() => {
    console.log(i);
  }, 100);
}

2. 立即执行函数表达式(IIFE,ES6之前的传统方案)

通过IIFE创建一个局部作用域,把当前循环的i值作为参数传入,让每个回调捕获这个局部变量:

for (var i = 0; i < 10; i++) {
  (function(currentI) {
    setTimeout(() => {
      console.log(currentI);
    }, 100);
  })(i);
}

3. 利用setTimeout的第三个参数

setTimeout允许传递额外参数给回调函数,我们可以把当前的i作为第三个参数传进去,回调直接使用这个参数:

for (var i = 0; i < 10; i++) {
  setTimeout((currentI) => {
    console.log(currentI);
  }, 100, i);
}

内容的提问来源于stack exchange,提问作者Navneet Dabral

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:03:07