javascript中閉包的一些理解

myux8313 7年前發布 | 13K 次閱讀 閉包 JavaScript開發 JavaScript

閉包是javascript中繞不開的話題,關于閉包的一些概念和應用,這方面資料比較多,在此就不再贅述。眾所周知,閉包的一個作用就是 讓一些變量始終保持在內存中 ,在此我用一些實際代碼對這句話作進一步的理解。

demo1:
function closure(){
  var n = 0;
  function test() {
    console.log(++n);
  }
  test() 
  test() 
}
a(); //輸出1,2(這個很好理解,不多說)

demo2:
function test(){
    var i=0;
    return function(){
        console.log(i++);
    }
    }
    var fn = test();
    fn(); //輸出0
    fn(); //輸出1

上述代碼中,fn就是執行函數test()返回的匿名函數。由于fn又是一個全局變量,生命周期一直存在,且這個匿名函數引用了父函數test里面的一個局部變量,所以變量i的狀態會被一直保存.

demo3:

function test(){
    var i=0;
    return function(){
        console.log(i++);
    }
}
test()(); //輸出0
test()(); //輸出0

上述代碼中,執行test()返回的是其內部的匿名函數,但是執行完test()()以后,該匿名函數的生命周期已經結束,所以變量i的狀態沒有得到保存。

最近在簡書上讀到一篇有趣的文章,其中一些代碼如下:

for (var i = 0; i < 5; i++) {
 setTimeout((function(i) {
    console.log(i);
  })(i), i * 1000);
}   //輸出0,1,2,3,4

上述代碼中有一個setTimeout()函數,其使用格式為setTimeout(func,time),意思是至少過time時間后,執行func。有了這樣的認識后,我們可以把func等價成:

(function(i){console.log(i)})(i)這個自執行函數。所以這個事情分兩步,首先每次循環自執行函數肯定會立即執行一次,會依次輸出1,2,3,4。其次,每過time時間,執行一次func,但是在上述代碼中,func等價于一個立即執行函數,沒有返回值,故什么也不會做。

如果把上述代碼改成這樣:

for (var i = 0; i < 5; i++) {
  var j=7;
  setTimeout((function(i) {
    console.log(i);
    return function(){
       console.info(j++);
    }
  })(i), i * 1000);
}

上述代碼會依次輸出0,1,2,3,4, 7,8,9,10,11(結合這個例子理解上一個問題,就容易多了)

如果把上面的代碼改成這樣呢?

for (var i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, i * 000);
}

運行上面的代碼會輸出5個5(這一點現在可以理解了吧),有人不解的是為什么是每隔一秒輸出5而不是隔五秒輸出5。setTimeout(func,time)這個函數延遲執行的只是func里面的動作,而time的值是不存在延遲的。上面執行for循環,相當于:setTimeout(func,1000),setTimeout(func,2000) .... 第一次setTimeout執行的時候等了一秒(準確地說,至少要等一秒),第二次setTimeout執行的時候等2秒,但是前面第一次執行的setTimeout函數時,已經等了一秒,所以只需再等一秒就可以立即執行了。在這里,需要弄明白的是,setTimeout函數延遲執行的時間,起點是從time開始賦值的時候計算的,不是從上一個setTimeout函數執行完開始算的。

 

來自:https://segmentfault.com/a/1190000008571702

 

 本文由用戶 myux8313 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!