一个经典的闭包面试题

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()
上一篇下一篇

猜你喜欢

热点阅读