for循環:閉包
for (var i=1; i<=5; i++) { setTimeout( function timer() { console.log( i ); }, i*1000 ); } /* 控制檯打印: 6 6 6 6 6 6 */
可是咱們但願的結果是:函數
1 2 3 4 5
緣由是,延遲函數的回調會在循環結束時才執行。當定時器運行時即便每一個迭代中執行的是setTimeout(.., 0),全部的回調函數依然是在循環結束後纔會被執行,所以會每次輸出一個6 出來。code
咱們改寫一下:作用域
for (var i=1; i<=5; i++) { (function() { setTimeout( function timer() { console.log( i ); }, i*1000 ); })(); } /* 6 6 6 6 6 */
緣由:若是做用域是空的,那麼僅僅將它們進行封閉是不夠的。它須要包含一點實質內容才能爲咱們所用。它須要有本身的變量,用來在每一個迭代中儲存i 的值:回調函數
繼續改寫:io
for (var i=1; i<=5; i++) { (function() { var j = i;//保存外部變量 setTimeout( function timer() { console.log( j ); }, j*1000 ); })(); } /* 1 2 3 4 5 */ //代碼改進:(將i當參數傳進去) for (var i=1; i<=5; i++) { (function(j) { setTimeout( function timer() { console.log( j ); }, j*1000 ); })( i ); }
總結console
當函數能夠記住並訪問所在的詞法做用域,即便函數是在當前詞法做用域以外執行,這時 就產生了閉包。