關於閉包與for循環的理解


 function createFunction1(){
            for(var i=0;i<5;i++){
              function s(){
                console.log(i);
              }
              s();
            }
          }
          createFunction1();   //0 1 2 3 4;

以上是一個正常的函數。

  function createFunction2(){
            for(var i=0;i<5;i++){
              setTimeout(function timer(){
                console.log(i);
              },i*1000);
            }
          }
          createFunction2();  //每隔1秒輸出‘4’、共輸出5次

並不會按照我們預想的每隔1秒分別輸出0、1、2、3、4

分析一下原因:

此函數在for循環的第一層是setTimeout函數,他的執行和createFunction1中的s函數一樣,將按分別在1秒后、2秒后、3秒后執行。但這兒需要注意的是,setTimeout的內部函數timer並沒有立即執行,for循環中的i將會把值分別賦給setTimeout外部參數中的i,但其內部函數timer()則只會引用包含函數setTimeout()中的變量的最后一個值。因為閉包所保存的是整個變量對象,而不是某個特殊的變量。當然其中的這些處理變化,都是瞬間完成的,與執行時間並無關系,即使把1000改成0效果還是一樣的。

重寫一下這個函數:

 function createFunction3(){
            for (var i=0;i<5;i++){
              (function(j){
                   setTimeout(function timer(){
                   console.log(j);
                  },i*1000);
              })(i);
            }
          }
          createFunction3();   //每隔1秒分別輸出0 1 2 3 4

再看上面這個例子,給外部包裝了一個立即執行的匿名函數,setTimeout里面的匿名函數不再引用外部函數的參數,而是直接引用外部匿名函數的參數,這時,一切就會按照我們預想的來執行了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM