天天看點

for循環中的setTimeout問題

原創内容,轉載請标記出處:https://blog.csdn.net/yihanzhi/article/details/79565628
//for循環1
for (var i = ; i < ; i++) {
    setTimeout(function () {
        console.log(i);
    },);
}
//for循環2
for (var i = ; i < ; i++) {
    setTimeout(function  (a) {
        console.log(a);
    }(i),);
}
輸出結果是:,,,,,
           

輸出結果可能會引起你的兩點質疑:

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 = ; i < ; i++) {
   setTimeout(function  () {
        console.log(i);
    },);
}
等價于
var i;//代碼行1
for (i = ; i < ; i++) {
    setTimeout(function  () {
        console.log(i);
    },);
}
           

因為var聲明的變量作用于函數作用域,函數中變量i指向代碼行1處聲明的變量,在for循環結束後i的值就是3,是以setTimeout執行時,其中的變量i值已經是3,為此輸出結果均是3。

循環2處的setTimeout中的函數是立即執行函數,不會等待定時器到點後再執行;可以把setTimeout中立即執行函數看作setTimeout外的普通函數,是以輸出結果合乎我們的意料。

繼續閱讀