淺談JavaScript中的閉包

1、閉包是什麼?

《JavaScript高級程序設計》中寫道:「閉包是指有權訪問另外一個函數做用域中的變量的函數」,若是用下定義的觀點看,這句話就是說「閉包是函數」,我帶着懷疑的心態又去網上找了找,發現什麼說法都有,終究沒能明白閉包的含義,仍是看代碼來得直接。閉包

function outter(){
  var sky="blue";
  function inner(){
    console.log(sky);
  }

  return inner;
}
var result=outter();
result();    //"blue"

這段代碼就包含一個簡單的閉包:outter函數的返回值是一個函數,即inner。inner在outter內部,理所固然能訪問到局部變量sky,但當inner做爲outter的返回值賦給outter外的全局變量時,神奇的事情發生了:在全局做用域中訪問到了sky,這就是閉包。函數

2、閉包的原理?

每一個函數都有本身的執行環境,當一個函數被執行時,它的執行環境就會被推入環境棧,其活動對象(存儲環境中定義的變量及函數)加入做用域鏈中,一旦函數執行完,棧將其環境彈出,活動對象被銷燬。this

對於上面的例子來講,outter執行完以後將返回inner給了result,outter的執行環境從環境棧彈出,控制權交給全局環境,outter的活動對象理應被銷燬。但此時inner已經存儲在全局活動對象中了,同時inner須要訪問sky,因此outter的活動對象沒有被銷燬,即便result執行完畢,outter的活動對象依然存在於做用域鏈中,只有當result被銷燬設計

result = null;

outter的活動對象纔會完全釋放。code

3、閉包有什麼用?

說了這麼多,閉包到底有什麼用呢?我我的認爲閉包最大的用處就是防止對全局做用域的污染。 試想若是咱們把一些僅僅只用到一兩次的變量都聲明在全局做用域中,最後確定是容易出錯且不可維護的。而閉包最神奇的地方就是能在一個函數外訪問函數中的局部變量,把這些變量用閉包的形式放在函數中便能避免污染。對象

4、Caveat

  • 閉包將函數的活動對象維持在內存中,過分使用閉包會致使內存佔用過多;ip

  • 閉包只能取得外部函數中任何變量的最後一個值,在使用循環且返回的函數中帶有循環變量時會獲得錯誤結果;內存

  • 當返回的函數爲匿名函數時,注意匿名函數中的this指的是window對象。作用域

相關文章
相關標籤/搜索