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

for迴圈中的閉包應用

1、下面程式碼的輸出為什麼?使下面程式碼的輸出結果為0 1 2 3 4,應如何修改下面的程式碼?請使用多種方式來實現
for(var i=0;i<5;i++){
  setTimeout(function(){
    alert(i);
  },100)
}

上述程式碼會輸出5個5。因為setTimeout是一個非同步任務,它會在迴圈完成後才進行,此時i=5.
若要實現輸出結果為0 1 2 3 4,也可以使用下列方法:

方法一:
    將for迴圈中的var,換為let關鍵字。

for(let i=0;i<5;i++){
  setTimeout(function(){
    alert(j);
  },100)
}

相當於以下程式碼:

for(var i=0;i<5;i++){
  let j=i;
  setTimeout(function(){
    alert(j);
  },100)
}

每次迴圈時建立一個塊級作用域下的j,setTimeout引用這個j,所以即使迴圈下去這個j,也不會被銷燬。

方法二:

for(var i=0;i<5;i++){
  (function(i){setTimeout(function(){
    alert(i);
  },100)})(i);
}

這裡使用閉包的方法,函式的作用域鏈在定義函式時就已經確定了,即函式內如果找到不到某個變數就會在定義該函式的環境中尋找該變數,而不是呼叫函式的環境中。
所以這裡通過為setTimeout這個非同步佇列外包裹一個自執行的匿名函式,函式的引數為i,就可以獲得每次迴圈時的i,而匿名函式內部沒有找到i,所以就在外層的匿名函式中尋找到i。即可實現0,1,2,3,4

參考文件:https://www.jianshu.com/p/132fb6d485ee