跳到主内容

一道循环异步输出问题引发的思考,没想到居然有3种解决方案

· 2分钟阅读

在前端面试,面试官想问一道闭包的面试题,基本离不开循环输出这道题。

for (var i = 0; i <= 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}

暂停想一想,输出的结果是什么?没错,结果是 4 个 4,因为 setTimeout 是异步的,当事件循环执行到回调队列时,此时的 i 已经是 4,所以输出的结果是 4,而不是 0,1,2,3。

那么如何解决呢?你会想出几种解决方案呢?

闭包

如果遇到过这个问题,可能印象第一时间会想到使用闭包,也没毛病,闭包可以维持变量在内存中,所以当定时器执行时,还是可以获取执行时的 i 的值。

for (var i = 0; i <= 3; i++) {
(function(i) {
setTimeout(function() {
console.log(i);
}, 1000);
})(i);
}

拆分函数

我们可以利用函数传值的按值传递的特性,通过新建一个函数来执行。

function timeout(val) {
setTimeout(function() {
console.log(val);
}, 1000);
}
for (var i = 0; i <= 3; i++) {
timeout(i);
}

块级作用域

利用ES6提供了块级作用域的特性

for (let i = 0; i <= 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}