閉包是指有權訪問另一個函數作用域中的變量的函數,個人認爲閉包最大的用處就是防止對全局作用域的污染。 試想如果我們把一些僅僅只用到一兩次的變量都聲明在全局作用域中,最後肯定是容易出錯且不可維護的。而閉包最神奇的地方就是能在一個函數外訪問函數中的局部變量,把這些變量用閉包的形式放在函數中便能避免污染。原文來源
一、閉包是什麼?
《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被銷燬
//code from http://caibaojian.com/javascript-closure.htmlresult = null;
outter的活動對象纔會徹底釋放。
三、閉包有什麼用?
說了這麼多,閉包到底有什麼用呢?我個人認爲閉包最大的用處就是防止對全局作用域的污染。 試想如果我們把一些僅僅只用到一兩次的變量都聲明在全局作用域中,最後肯定是容易出錯且不可維護的。而閉包最神奇的地方就是能在一個函數外訪問函數中的局部變量,把這些變量用閉包的形式放在函數中便能避免污染。
四、Caveat
- 閉包將函數的活動對象維持在內存中,過度使用閉包會導致內存佔用過多;
- 閉包只能取得外部函數中任何變量的最後一個值,在使用循環且返回的函數中帶有循環變量時會得到錯誤結果;
- 當返回的函數爲匿名函數時,注意匿名函數中的this指的是window對象。