setTimeout定時器的異步及let循環中的同步異步問題 個人理解筆記

新手個人理解  如有誤解   敬請各位前輩評論指出 謝謝

例1: for循環setTimeout定時器:

for(var i = 1 ; i <= 5; i++){
(function(){
    setTimeout(function timer(){
        console.log(i);
        }
,1000*i);
    })();

}

上述代碼預期分別輸出 1  2  3  4  5   但是實際輸出 6  6  6  6  6

原因:由於for循環與setTimeout函數是同步執行函數,而console.out是異步執行函數。異步執行函數需等待同步執行函數執行完畢纔開始執行。所以當for循環與定時器全部加載執行完畢放進執行棧之後(即i=6時)console.log開始初始化。所以就出現了五次定時器循環的輸出6.

例2: 函數實參傳遞:

for(var i = 1 ; i <= 5; i++){
(function(j){
    setTimeout(function timer(){
        console.log(j);
        }
,1000*j);
    })(i);

}

而這種寫法就可以正確的輸出預期結果。因爲函數內不是直接傳遞for循環的值,將for循環與函數分離開來,通過參數的傳遞連接。這樣console.log就不用等待for循環全部執行完畢。

例3: let循環的setTimeout定時器:

for(let i = 1 ; i <= 5; i++){
    (function(){
        setTimeout(function timer(){
        console.log(i);
        }
,1000*i);

    })();

}

let定義的循環體也是可以正常輸出預期。因爲let的作用域實在代碼塊中,聲明只能在自身的塊裏聲明,不是像var那樣作用於函數,所以就等於每一次循環都重新定義一次let i,這樣循環就只能一次次給函數傳值。在這裏let本質上就是形成了一個閉包,就像例4。

例4:

var loop = function(_i){
setTimeout(function timer(){
console.log(_i);
},1000*_i);

}

for(var i = 1 ; i <= 5; i++){
loop(i);

}

閉包概念:當內部函數以某一種方式被任何一個外部函數作用域訪問時,一個閉包就產生了!




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章