好程式設計師技術分享淺談JavaScript中的閉包
好程式設計師技術分享淺談JavaScript中的閉包,js閉包是指有權訪問另一個函式作用域中的變數的函式,個人認為js閉包最大的用處就是防止對全域性作用域的汙染。 試想如果我們把一些僅僅只用到一兩次的變數都宣告在全域性作用域中,最後肯定是容易出錯且不可維護的。而閉包最神奇的地方就是能在一個函式外訪問函式中的區域性變數,把這些變數用閉包的形式放在函式中便能避免汙染。
一、閉包是什麼?
《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,這就是閉包。
二、閉包的原理?
每個函式都有自己的執行環境,當一個函式被執行時,它的執行環境就會被推入環境棧,其活動物件(儲存環境中定義的變數及函式)加入作用域鏈中,一旦函式執行完,棧將其環境彈出,活動物件被銷燬。
對於上面的例子來說,outter執行完之後將返回inner給了result,outter的執行環境從環境棧彈出,控制權交給全域性環境,outter的活動物件理應被銷燬。但此時inner已經儲存在全域性活動物件中了,同時inner需要訪問sky,所以outter的活動物件沒有被銷燬,即使result執行完畢,outter的活動物件依然存在於作用域鏈中,只有當result被銷燬
null;
outter的活動物件才會徹底釋放。
三、閉包有什麼用?
說了這麼多,閉包到底有什麼用呢?我個人認為閉包最大的用處就是防止對全域性作用域的汙染。 試想如果我們把一些僅僅只用到一兩次的變數都宣告在全域性作用域中,最後肯定是容易出錯且不可維護的。而閉包最神奇的地方就是能在一個函式外訪問函式中的區域性變數,把這些變數用閉包的形式放在函式中便能避免汙染。
四、Caveat
· 閉包將函式的活動物件維持在記憶體中,過度使用閉包會導致記憶體佔用過多;
· 閉包只能取得外部函式中任何變數的最後一個值,在使用迴圈且返回的函式中帶有迴圈變數時會得到錯誤結果;
· 當返回的函式為匿名函式時,注意匿名函式中的this指的是w