如何理解setTimeout里面的异步?

比如:

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

我一直以为这里是因为闭包才输出10个10,后来面试官告诉我是因为异步,为什么是异步呢?

阅读 10.9k
9 个回答
  1. 你问为什么这里输出10的原因是异步?
    我只能告诉你,因为setTimeout()函数是异步的

  2. 为什么setTimeout()函数是异步的?
    这个问题你得去问Brendan Eich

  3. 如果你想问的是这里为什么输出10?
    因为异步函数必须等主进程运行完毕才会运行,setTimeout()内部回调运行的时候,主进程已经运行完毕了,此时i=10,所以输出10。

setTimeout的延迟不是绝对精确的;
setTimeout的意思是传递一个函数,延迟一段时候把该函数添加到队列当中,并不是立即执行;
所以说如果当前正在运行的代码没有运行完,即使延迟的时间已经过完,该函数会等待到函数队列中前面所有的函数运行完毕之后才会运行;也就是说所有传递给setTimeout的回调方法都会在整个环境下的所有代码运行完毕之后执行

    setTimeout(function(){
        console.log("here");
    }, 0);
    var i = 0;
    //具体数值根据你的计算机CPU来决定,达到延迟效果就好
    while (i < 3000000000) {
        i ++;
    }
    console.log("test");

运行以上代码,你会发现,上面的函数会等待while循环执行完毕之后才会运行,同时你还会发现,here输出在test的后面;

用伪代码表示就是(顺序自上而下)
主线程:

for (var i = 0; i < 10; i++) {
    setTimeout(function() {
    }, 0);
    //注册了10个定时器
}
//....执行其他的代码

//执行异步代码:
//这时i已经变成了10,i=10;
//console.log(i)  10次

异步其实就是你去吃饭,但是厨师告诉你不能立即做好,需要等一段时间(主线程在跑其他代码)。
然后因为你很饿,所以你催了10次(注册了10次异步)。
等厨师有时间了,才回应你的要求并且给你做饭。

setTimeout(function(){
    console.log(1);
}, 2000);
console.log(2);

你看看 1 先输出还是 2 先输出,所谓异步,就是脱离你目前的执行流程。

因为 settimeout 就是被设计成异步的啊,难不成你是想问它为什么是异步的!

哪里有闭包? 闭包是为了不输出 10 个 10 吧?

这里绝对有闭包的作用,你不知道的js上册说的很清楚。
比如
for( var i=1; i<=10; ++i ){

(function(){
    var j = i
    setTimeout( function(){console.log(j)},0 )
})()

}
这里就会输出1,2,3。。。。10

推荐问题
宣传栏