新手個人理解 如有誤解 敬請各位前輩評論指出 謝謝
例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);
}
閉包概念:當內部函數以某一種方式被任何一個外部函數作用域訪問時,一個閉包就產生了!