一个经典的闭包面试题
2018-10-28 本文已影响12人
本一和他的朋友们
Shut up, show me the code!!!
function showBiBao() {
for (var i = 0; i < 5; i++) {
setTimeout( function timer() {
console.log(i);
}, 1000 );
}
console.log(i)
}
// 会输出什么
showBiBao()
会用到的两个知识点:
闭包
setTimeout
提示:
这个代码是有bug的,怎么解决?
解决方法:
第一步:先找出bug原因
1.1:for循环5次,那么应该设定了5个定时器,这个没错
1.2:setTimeout等待for循环执行完成后立即调用定时器
1.3:setTimeout被放在了队列的数据结构中(for循环),等待上下文的代码运行后再执行定时器,此时运行定时器,变量i已经变成了5(此时5个定时器的i都是5),所以输出全是5
第二步:怎么解决?
2.1:需要把每个定时器访问的变量独立起来,改变i的作用域
2.1:可以用闭包实现这个目的:在for循环里写一个闭包
2.3:show code
function showListNumber() {
for(var i = 0; i < 5; i++) {
(function(i) {
setTimeout(function timerr() {
console.log(i)
}, 1000)
})(i)
}
console.log(i)
}
showListNumber()
第三步:还能怎么做?
3.1:改变i的作用域就可以消除bug
3.2:可以用let声明一个仅对当前{}(块作用域)内有效的变量。
function useLetChange() {
for (let i = 0; i < 5; i++) {
setTimeout( function timer() {
console.log(i);
}, 1000 );
}
}
useLetChange()