閉包的定義:閉包是指有權訪問另一個函式作用域中的變數的函式 --《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函式,容易導致記憶體中的垃圾資料越來越多造成記憶體泄漏,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/142382.html
標籤:JavaScript
