在前端面试,面试官想问一道闭包的面试题,基本离不开循环输出这道题。
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);
}