closertb / closertb.github.io

浏览issue 或 我的网站,即可查看我的所有博客
https://closertb.site
32 stars 0 forks source link

详解前端网红面试题:setTimeout与循环闭包 #4

Open closertb opened 5 years ago

closertb commented 5 years ago

写于:2017-06-08

最近一道面试试题非常火热,堪称面试界网红:

function test(){
    for (var i=0; i<5; i  ) {
        setTimeout( function timer() {
            console.log(new Date(),i);
        }, 1000 );
    }
    console.log('end',new Date(),i); //为方便后边演示,这里加了打印end标志
}

不理解闭包,变量作用域和setTimeout函数的同学很多会给出答案A:0,1,2,3,4,5和答案B:5,0,1,2,3,4;不奇怪,但正确答案却是5,5,5,5,5,我以前也是。当然相比较,说出答案B至少比答案A多知道setTimeout函数的用法,重点不在那个延迟1000ms,重点在setTimeout函数,后面会细说。 首先三个概念:

image

在for循环声明的五个TimeOut Callback函数都有对变量i的引用,而不是拷贝。因为5个timeout函数都涉及到延迟执行的情况,所以当主线程执行完后(end被打印时),timeout这些回调依次执行(队列:FIFO),此时i的值已经为5了,知道以上这些,后面就简单多了。

开始回到正题: 其实写出这个函数期望输出5,0,1,2,3,4,要达到这个结果,方法有多种,这里列出典型的三种: