在javascript中,閉包指的就是一個函數;當兩個函數彼此嵌套時,內部的函數就是閉包。典型的閉包體是巢狀結構的函數;內部函數引用外部函數的私有成員,同時內部函數又被外界引用,當外部函數被呼叫後,就形成了閉包。
本教學操作環境:windows7系統、javascript1.8.5版、Dell G3電腦。
什麼是閉包
所謂閉包,指的就是一個函數。當兩個函數彼此巢狀時,內部的函數就是閉包。
形成原理
函數被呼叫時,會產生一個暫存上下文活動物件。它是函數作用域的頂級對象,作用域內所有私有方法有變數、參數、私有函數等都會作為上下文活動對象的屬性而存在。
函數被呼叫後,在預設情況下上下文活動物件會被立即釋放,避免佔用系統資源。但是,若函數內的私有變數、參數、私有函數等被外界引用,則這個上下文活動物件暫時會繼續存在,直到所有外界引用都被註銷。
但是,函數作用域是封閉的,外界無法存取。那麼在什麼情況下,外界可以存取函數內的私有成員呢?
根據作用域鏈,內部函數可以存取外部函數的私有成員。如果內部函數引用了外部函數的私有成員,同時內部函數又被傳給外界,或是對外界開放,那麼閉包體就形成了。這個外部函數就是一個閉包體,它被呼叫後,活動物件暫時不會被註銷,其屬性會繼續存在,透過內部函數可以持續讀寫外部函數的私有成員。
閉包結構
典型的閉包體是一個巢狀結構的函數。內部函數引用外部函數的私有成員,同時內部函數又被外界引用,當外部函數被呼叫後,就形成了閉包。這個函數也稱為閉包函數。
下面是一個典型的閉包結構。
function f(x) { //外部函数 return function (y) { //内部函数,通过返回内部函数,实现外部引用 return x + y; //访问外部函数的参数 }; } var c = f(5); //调用外部函数,获取引用内部函数 console.log(c(6)); //调用内部函数,原外部函数的参数继续存在
解析過程簡單描述如下:
在 JavaScript 腳本預編譯期,宣告的函數 f 和變數 c,先被詞法預先解析。
在 JavaScript 執行期,呼叫函數 f,並傳入值 5。
在解析函數 f 時,會建立執行環境(函數作用域)和活動對象,並將參數和私有變數、內部函數都映射為活動對象的屬性。
參數 x 的值為 5,對應到活動物件的 x 屬性。
內部函數透過作用域連結引用了參數 x,但是還沒有被執行。
外部函數被呼叫後,傳回內部函數,導致內部函數被外界變數 c 引用。
JavaScript 解析器偵測到外部函數的活動對象的屬性被外界引用,無法註銷該活動對象,於是在記憶體中繼續維持該對象的存在。
當呼叫 c,也就是呼叫內部函數時,可以看到外部函數的參數 x 儲存的值繼續存在。這樣就可以實現後續運算操作,回傳 x y=5=6=11。
閉包的價值是方便在表達式運算過程中儲存資料。但是,它的缺點也不容忽視:
由於函數呼叫後,無法登出呼叫對象,會佔用系統資源,在腳本中大量使用閉包,容易導致記憶體洩漏。解決方法:慎用閉包,不要濫用。
由於閉包的作用,其保存的值是動態,如果處理不當容易出現異常或錯誤。
【相關推薦:javascript學習教學】
以上是javascript閉包啥意思的詳細內容。更多資訊請關注PHP中文網其他相關文章!