为何这段代码重复输出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
相关产品推荐
相关产品推荐

