js 閉包原理


閉包的定義:閉包是指有權訪問另一個函數作用域中的變量的函數  --《JavaScript 高級程序設計》。

如何理解這句話:其實就是指在函數a外面能夠訪問函數a里面的函數b

例如:

 1 function a () {
 2   var v = 123;
 3   function b() {
 4     console.log(v);
 5   }
 6   return b;
 7 }
 8 
 9 var b = a();
10 b();  // 123

執行函數a時把函數b返回,此時函數b就保存到了a的外面,這時候就可以在a函數的外部對b進行訪問。

 

相關知識點:js作用域鏈

執行原理:

1、首先在預編譯全局代碼時,生成GO

  GO {

    a: function a() {...},

    b: undefined

  }

2、執行 var b = a();  此時對a函數進行預編譯並創建a 函數的AO 

  AO {

    v: undefined,

    a: undefined,

    b: function b() {...}

  }

3、創建a函數的作用域鏈

  a.[[Scopes]] = [AO, GO];  

4、由於函數的提升,會在a函數進行預編譯的時候創建b函數的AO

  b  AO {}

  b.[[Scopes]] = [AO(b), AO(a), GO]

5、執行 var v = 123;  在js預編譯中提到由於var v 的聲明已經得到了提升,所以此時只執行v = 123;對AO里的v 進行賦值。

  AO {

    v: 123,

    a: undefined,

    b: function b() {...}

  }

6、之后將函數b返回,此時a函數執行完畢,a函數對應的AO理應銷毀,但是由於在b函數中又對a函數的AO中的變量進行應用,所以a函數的AO不能被垃圾回收機制銷毀,但是會跟a函數斷開聯系,當a函數再次執行,會重新創建一個a函數的AO。

7、在全局變量中使用b 接收函數a的返回,此時GO變為

  GO {

    a: function a() {...},

    b: function b() {...}

  }

 

8、全局里的b

  在b函數中打印v變量,由於b函數的AO中沒有v變量,所以順着作用域鏈往上找,在a的AO中找到v並打印。

 

閉包優缺點:

  優點:

    1、屬性的私有化,在b返回后,處理b函數中能對v進行操作,其它地方都不能對v進行操作。

    2、防止變量污染。

  缺點:

    容易造成內存泄漏,因為如果后期不對全局中的b進行處理(例如:賦值為null),a函數的AO 會一直存在於內存中,如果多次調用a函數,容易導致內存中的垃圾數據越來越多造成內存泄漏。


免責聲明!

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



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