瀏覽器工作原理簡單說明 瀏覽器基本原理



文章插圖
瀏覽器工作原理簡單說明 瀏覽器基本原理

文章插圖
Q:
function fn() {var a = 10function f1() {console.log(a)};function f2() {console.log('f2')};f2();};fn();我在函數f2里打斷點,當執行到函數f2時,chrome里顯示Closure:{a:10},如果把這個原因解釋為在fn函數里會預掃描f1函數,那我現在把fn2函數和調用都注釋了,現在執行fn函數時不產生Closure,為什么就不預掃描f1函數了?這是為什么?
A:
你把f2注釋了,當執行fn函數時,照樣會預掃描f1,照樣會產生閉包,只不過當fn執行結束之后,閉包的內容沒有外部引用,那么下次垃圾回收直接把比閉包的內容回收掉
Q:
從內存模型角度分析執行代碼的執行流程第二步看,在堆空間創建closure(foo)對象,它是存儲在foo函數的執行上下文中的 。那么closure(foo)創建開始時是空對象,執行第三步的時候,才會逐漸把變量添加到其中 。當foo函數執行結束后,foo的執行上下文是不是銷毀了?如果銷毀了,產生以下兩個疑問:如果foo函數執行上下文銷毀了,closure(foo)并沒有銷毀,那foo函數執行上下文是怎么銷毀的呢?就比如銷毀一個盒子,盒子毀里,里面的東西應該也是毀掉的既然closure(foo)既然沒有銷毀,那它存儲在堆中的什么地方呢?畢竟所依賴的foo執行上下文已經不存在了
A:
關于foo函數執行上下文銷毀過程:foo函數執行結束之后,當前執行狀態的指針下移到棧中的全局執行上下文的位置,foo函數的執行上下文的那塊數據就挪出來,這也就是foo函數執行上下文的銷毀過程,這個文中有提到,你可以參考“調用棧中切換執行上下文狀態“圖 。
第二個問題:innerBar返回后,含有setName和getName對象,這兩個對象里面包含了堆中的closure(foo)的引用 。雖然foo執行上下文銷毀了,foo函數中的對closure(foo)的引用也斷開了,但是setName和getName里面又重新建立起來了對closure(foo)引用 。
你可以:
打開“開發者工具”在控制臺執行上述代碼然后選擇“Memory”標簽,點擊”take snapshot” 獲取V8的堆內存快照 。然后“command+f”(mac) 或者 “ctrl+f”(win),搜索“setName”,然后你就會發現setName對象下面包含了 raw_outer_scope_info_or_feedback_metadata,對閉包的引用數據就在這里面 。
Q:
Function 函數類型也是繼承于Object,聲明函數后是不是也是存在堆空間中的,那么瀏覽器編譯函數時是不是會同時創建執行上下文和向堆空間中壓入一個值function a(){ var b = 1; var c = { d: 2 }; }當 a 的執行上下文銷毀后,c 對象在堆空間中的引用會跟著銷毀么,將 c 返回出去或不返回,會不會是不一樣的情況
A:
函數就是一種特別的對象,所以會保存在堆上,編譯函數時,這個函數就已經存在于堆中了!
【瀏覽器工作原理簡單說明 瀏覽器基本原理】第二個問題返回了c對象的話,那么說明全局環境對c對象有引用,既然有引用那么就不會被垃圾回收器標記出來,所以c對象也就不會回收!