本次筆記主要記錄了:bash
閉包與垃圾回收機制的關係,微信
閉包與做用域鏈的關係。閉包
在系列(二)中,我提到了垃圾回收機制,知道當一個值失去引用以後就會被標記,而後被垃圾回收機制回收並釋放空間。函數
咱們知道,當一個函數的執行上下文運行完畢以後,內部全部內容都會失去引用而被垃圾回收機制回收。性能
咱們還知道,閉包的本質就是在函數外部保持了內部變量的引用,所以很明顯閉包會阻止垃圾回收機制回收。學習
下面咱們就用一個例子來證實這一點。ui
function f1() {
var n = 999;
nAdd = function() {
n += 1;
}
return function f2() {
consloe.log(n);
}
}
var result = f1();
result(); //999
nAdd();
result(); //1000複製代碼
從上面的例子能夠看出,由於nAdd、f2都訪問了f1中的n,所以它們都與f1造成了閉包。這個時候變量n的引用被保留了下來。由於f2與nAdd執行時都訪問了n,而nAdd每運行一次就會將n加1.spa
認識到閉包中保存的內容不會被釋放以後,咱們就應該謹慎使用閉包。由於誰都知道,閉包的濫用可能會致使內存泄露於是影響程序性能。code
在開始以前,先思考一個問題,閉包會致使函數的做用域鏈發生改變嗎?cdn
咱們結合下面的例子來分析一下。
var fn = null;
function foo() {
var a = 2;
function innerFoo() {
console.log(a);
}
fn = innerFoo; // 將innerFoo的引用賦值給全局變量中的fn
}
function bar() {
fn(); //此處保留innerFoo的引用
}
foo();
bar(); //2複製代碼
在這個例子中,foo內部的innerFoo訪問了foo的變量a。所以當innerFoo執行時會有閉包產生,這是一個比較簡單的閉包的例子。不同的地方在與全局變量fn。fn在foo內部獲取了innerFoo的引用,並在bar中執行。
那麼innerFoo的做用域鏈會是怎麼樣的呢?
在這裏須要特別注意的地方是函數調用棧與做用域鏈的區別:
由於call stack實際上是在代碼執行時才肯定的,而做用域的規則在代碼編譯階段就已經肯定了。雖然做用域鏈的在代碼執行時才生成的,可是他的規則不會隨着代碼執行而發生變化。
so,這裏的閉包的存在並不會致使做用域鏈發生變化。
這些都是我以往的學習筆記。若是您看到此筆記,但願您能指出個人錯誤。有這麼一個羣,裏面的小夥伴互相監督,堅持天天輸出本身的學習心得,不輸出就出局。但願您能加入,咱們一塊兒終身學習。歡迎添加個人我的微信號:Pan1005919589