閉包是一個比較抽象的概念,尤其是對js新手來說.書上的解釋實在是比較晦澀,對我來說也是一樣.
但是他也是js能力提升中無法繞過的一環,幾乎每次面試必問的問題,因爲在回答的時候.你的答案的深度,對術語的理解以及js內部解釋器的運作方式的描述,都是可以看出你js實際水平的.即使你沒答對,也能讓考官對你的水平有個評估.那麼我先來說說我對js中的閉包的理解.
閉包是很多語言都具備的特性,在js中,閉包主要涉及到js的幾個其他的特性:作用域鏈,垃圾(內存)回收機制,函數嵌套,等等.
在理解閉包以前.最好能先理解一下作用域鏈的含義,簡單來說,作用域鏈就是函數在定義的時候創建的,用於尋找使用到的變量的值的一個索引,而他內部的規則是,把函數自身的本地變量放在最前面,把自身的父級函數中的變量放在其次,把再高一級函數中的變量放在更後面,以此類推直至全局對象爲止.當函數中需要查詢一個變量的值的時候,js解釋器會去作用域鏈去查找,從最前面的本地變量中先找,如果沒有找到對應的變量,則到下一級的鏈上找,一旦找到了變量,則不再繼續.如果找到最後也沒找到需要的變量,則解釋器返回undefined.
瞭解了作用域鏈,我們再來看看js的內存回收機制,一般來說,一個函數在執行開始的時候,會給其中定義的變量劃分內存空間保存,以備後面的語句所用,等到函數執行完畢返回了,這些變量就被認爲是無用的了.對應的內存空間也就被回收了.下次再執行此函數的時候,所有的變量又回到最初的狀態,重新賦值使用.但是如果這個函數內部又嵌套了另一個函數,而這個函數是有可能在外部被調用到的.並且這個內部函數又使用了外部函數的某些變量的話.這種內存回收機制就會出現問題.如果在外部函數返回後,又直接調用了內部函數,那麼內部函數就無法讀取到他所需要的外部函數中變量的值了.所以js解釋器在遇到函數定義的時候,會自動把函數和他可能使用的變量(包括本地變量和父級和祖先級函數的變量(自由變量))一起保存起來.也就是構建一個閉包,這些變量將不會被內存回收器所回收,只有當內部的函數不可能被調用以後(例如被刪除了,或者沒有了指針),纔會銷燬這個閉包,而沒有任何一個閉包引用的變量纔會被下一次內存回收啓動時所回收.
//閉包函數操作
(function(w){
//私有的數據
var money=1000;
//提供操作有數據的函數
function get(){
money =money*10;
console.log("賺了一筆錢,總資產"+money+"元")
}
function send(){
money--;
console.log("花了一筆錢,總資產"+money+"元")
}
//向外部暴露對象
w.myTool={
'get':get,
'send':send
}
})(window)//傳window參數
//通過window調用
window.myTool.get();
window.myTool.send();