瀏覽器工作原理簡單說明,瀏覽器工作原理詳解

Q:

function fn() {
    var a = 10
    function 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)引用。

你可以:

  1. 打開“開發者工具”
  2. 在控制台執行上述代碼
  3. 然後選擇“Memory”標籤,點擊”take snapshot” 獲取V8的堆內存快照。
  4. 然後“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對象也就不會回收!

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/232917.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-11 13:23
下一篇 2024-12-11 13:23

相關推薦

發表回復

登錄後才能評論