for循环中的setTimeout问题

原创内容,转载请标记出处:https://blog.csdn.net/yihanzhi/article/details/79565628

//for循环1
for (var i = 0; i < 3; i++) {
    setTimeout(function () {
        console.log(i);
    },0);
}
//for循环2
for (var i = 0; i < 3; i++) {
    setTimeout(function  (a) {
        console.log(a);
    }(i),0);
}
输出结果是:0,1,2,3,3,3

输出结果可能会引起你的两点质疑:
1)延迟的时间同样为0,为何先执行下面的for循环呢?
2)为何循环1处的for循环输出结果都是3,循环2处的for循环是0,1,2呢?

疑点解答:
1)延迟的时间同样为0,为何先执行下面的for循环呢?

    function  (a) {
        console.log(a);
    }(i)

函数后加()表示是一个立即执行函数,在setTimeout函数执行调用时就被执行了,而不是等到定时器到点后被执行;而setTimeout(fn,0)并不是立即执行,只是表示下一次事件循环到达时可以马上执行
备注:setTimeout绑定的回调函数只是往Javascript的事件循环机制中注册了一个定时器,这个定时器只可能在当前事件循环的下一次事件循环中才有可能被执行。

2)为何循环1处的for循环输出结果都是3,循环2处的for循环是0,1,2呢?

for (var i = 0; i < 3; i++) {
   setTimeout(function  () {
        console.log(i);
    },0);
}
等价于
var i;//代码行1
for (i = 0; i < 3; i++) {
    setTimeout(function  () {
        console.log(i);
    },0);
}

因为var声明的变量作用于函数作用域,函数中变量i指向代码行1处声明的变量,在for循环结束后i的值就是3,所以setTimeout执行时,其中的变量i值已经是3,为此输出结果均是3。
循环2处的setTimeout中的函数是立即执行函数,不会等待定时器到点后再执行;可以把setTimeout中立即执行函数看作setTimeout外的普通函数,所以输出结果合乎我们的意料。

猜你喜欢

转载自blog.csdn.net/yihanzhi/article/details/79565628