為什麼js會有閉包
前兩天阿里的面試,gg了。不過還是收穫良多。阿里的面試沒有怎麼聊到框架,都是原生和底層的東西比較多。
期間,對面大哥問我,為什麼js會有閉包?
我一愣,說我理解的是,js的閉包其實是對js函式作用域特性的一種利用,因為函式內定義的區域性變數不能被外部直接獲取,而函式卻可以訪問到其外部作用域的變數。所以我們可以在函式內部定義一個訪問區域性變數的方法並將之輸出給外部。在函式銷燬後,通過函式輸出的方法訪問區域性變數成了唯一途徑。(當時大概說了這些,其實答的是“什麼是閉包”。。。)
對面沒說話。
我試探性地補充說:通過閉包,我們可以避免全域性汙染,保護私密資料云云。
對面沒說話。
我急了:呃。。我們平時建立的自執行匿名函式也是一種閉包,解析器讀到那對括號,還將至視為一個表示式立即執行blabla
對面說:這些都不是我想聽的答案,能從更底層一些的角度講講嗎?
我:哈。。。
後來也問到js引擎和node的記憶體管理。
週末的時候重新看了下js引擎的工作過程,對這個問題有了新的認識。簡單來說,js引擎的工作分兩個階段,一個是語法檢查階段,一個是執行階段。而執行階段又分預解析和執行兩個階段。
在預解析階段,先建立執行上下文,執行上下文包括變數物件、作用域鏈和this值。
變數物件VO:var宣告的變數、function宣告的函式,及當前函式的形參
作用域鏈:當前變數物件+所有父級作用域 [[scope]]
this值:在進入執行上下文後不再改變
PS:作用域鏈其實就是一個變數物件的鏈,函式的變數物件稱之為active object,簡稱AO。函式建立後就有靜態的[[scope]]屬性,直到函式銷燬)
建立執行上下文後,會對變數物件的屬性進行填充。所謂屬性,就是var、function宣告的標誌符及函式形參名,至於屬性對應的值:變數值為undefined,函式值為函式定義,形參值為實參,沒有傳入實參則為undefined。
預解析階段結束後,進入執行程式碼階段,此時執行上下文有個Scope屬性(區別於函式的[[scope]]屬性)。
Scope = 當前AO.concat([[scope]])
js解析器逐行讀取並執行程式碼,變數物件中的屬性值可能因賦值語句而改變。當我們查詢外部作用域的變數時,其實就是沿著作用域鏈,依次在這些變數物件裡遍歷標誌符,直到最後的全域性變數物件。
回到閉包這個問題。當別人問你為什麼會有閉包這東西的時候,其實是在問,閉包的形成機制。
function outer(){
var a1=0;
return function inner(){
return a1;
}
}
function fn(){
var getInnerData = outer();
console.dir(getInnerData)
}
fn();
當我們呼叫一個閉包函式時(比如上面的getInnerDate函式),因為函式執行時,其上下文有個Scope屬性,該屬性作為一個作用域鏈包含有該函式被定義時所有外層的變數物件的引用,所以定義了閉包的函式雖然銷燬了,但是其變數物件依然被繫結在函式inner上,保留在記憶體中。
事實上,只要程式碼保持對getInnerDate函式的引用,函式自身的[[scope]]屬性就繫結著閉包的活動物件。
但要留意的是,基於js的垃圾回收機制,outer的變數物件裡,只有仍被引用的變數會繼續儲存在記憶體中:
參考:
相關文章
- JS 裡為什麼會有 thisJS
- [JS]什麼是閉包?JS
- JS 中的閉包是什麼?JS
- 閉包函式到底是什麼?有什麼用?函式
- Python中什麼是閉包?閉包的好處是什麼?Python
- NuGet是什麼?為什麼.NET專案中會有NuGet?如何使用NuGet程式包?
- mac os 關閉sip保護有什麼好處?有什麼壞處?macOS為什麼關閉sip?Mac
- 什麼是閉包陷阱?
- 什麼是閉包?有哪些使用場景?優缺點是什麼?
- javascript中閉包是什麼JavaScript
- 為什麼會有這麼多程式語言
- with open為什麼會自動關閉檔案流
- 征服 JavaScript 面試:什麼是閉包JavaScript面試
- 面試:你知道為什麼會有 Generator 嗎面試
- 為什麼會有 Python 3 的存在?Python
- 為什麼Facebook不會有“dislike”按鈕?
- 為什麼會有深度學習?如何看待?深度學習
- 為什麼會有這麼多的程式語言?
- JS閉包ClosureJS
- js--閉包JS
- js-閉包JS
- [譯] JavaScript 中為什麼會有 Symbol 型別?JavaScriptSymbol型別
- mos管為什麼會有寄生二極體
- 為什麼會有這麼多種的資料庫資料庫
- 什麼是過時閉包及如何解決過時閉包的坑
- 為什麼抓包檔案有好幾種型別?型別
- js函式閉包JS函式
- js閉包的理解JS
- 淺談js閉包JS
- js中的閉包JS
- js閉包測試JS
- Javascript之旅——第十站:為什麼都說閉包難理解呢?JavaScript
- fastjson到底做錯了什麼?為什麼會被頻繁爆出漏洞?ASTJSON
- [Python小記] 通俗的理解閉包 閉包能幫我們做什麼?Python
- JSON是什麼,有什麼用,怎麼寫jsonJSON
- 伺服器發包指的是什麼?有什麼作用?伺服器
- js閉包及閉包的經典使用場景JS
- Spring——為什麼會有迴圈依賴(原始碼)Spring原始碼