1. 程式人生 > >迴圈中的閉包 for中套用setTimeout

迴圈中的閉包 for中套用setTimeout

迴圈中的閉包

一個常見的錯誤出現在迴圈中使用閉包,假設我們需要在每次迴圈中呼叫迴圈序號

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

上面的程式碼不會輸出數字 0 到 9,而是會輸出數字 10 十次。

當 console.log 被呼叫的時候,匿名函式保持對外部變數 i 的引用,此時 for迴圈已經結束, i 的值被修改成了 10

.

為了得到想要的結果,需要在每次迴圈中建立變數 i 的拷貝

避免引用錯誤

為了正確的獲得迴圈序號,最好使用 匿名包裝器譯者注其實就是我們通常說的自執行匿名函式)。

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

外部的匿名函式會立即執行,並把 i 作為它的引數,此時函式內 e 變數就擁有了 i

 的一個拷貝。

當傳遞給 setTimeout 的匿名函式執行時,它就擁有了對 e 的引用,而這個值是不會被迴圈改變的。

有另一個方法完成同樣的工作,那就是從匿名包裝器中返回一個函式。這和上面的程式碼效果一樣。

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