JavaScript 執行線程圖解

java進階程序員xx 發佈 2020-02-29T18:47:25+00:00

這是研究 JavaScript 內部工作方式的系列文章的第一篇。我會盡力使它變得有趣,並且不讓你感到厭煩,因為我知道這些東西有時會變得非常乏味!想像一下,飛行員知道是飛機怎樣飛行的,而我們每天運行 JavaScript 代碼,但知道它是如何運行嗎?

這是研究 JavaScript 內部工作方式的系列文章的第一篇。我會盡力使它變得有趣,並且不讓你感到厭煩,因為我知道這些東西有時會變得非常乏味!

想像一下,飛行員知道是飛機怎樣飛行的,而我們每天運行 JavaScript 代碼,但知道它是如何運行嗎?

談談 JavaScript 執行線程

先讓我們敲出一些簡單的 JavaScript 代碼:

const num = 3;
function addOne(x) {
  const result = x + 1;
  return result;
}

const output = addOne(num);

上面的代碼沒什麼讓你值得興奮的,但是可以很好地幫助我們演示執行線程。

當執行 JavaScript 時,代碼會逐行(單線程)執行,因此在我們的代碼中,要被執行的第一行是:

1const num = 3;

下一個問題是,執行這行代碼會發生什麼?num 存儲在哪裡?

num 存儲在全局內存/執行上下文中,看起來像這樣:

顯示如何執行第一行的動畫

然後進入下一行:

1function addOne(x) {

請務必注意,我們在這裡聲明了一個函數,但是還不執行。因此,我們將函數名稱與整個函數的值一起存儲。

第二行如何執行

上面的 - f - 是整個函數的簡寫。

現在轉到下一行,有人可能認為下一行是函數的主體,但是由於我們僅聲明函數而不是運行它,因此要運行的下一行是:

1const output = addOne(num);

與上面類似,我們將標籤 output 發送到內存,但還沒有值,因為我們必須運行函數。

保存函數標籤

有趣的來了!接下來執行 addOne 函數。

當一個函數被執行時,它被添加到 call stack (調用棧)中。調用堆棧的底部總是有 global / main ,我們現在將 addOne(3) 入棧。

調用堆棧

我們還為該函數創建一個 execution context (執行上下文)。函數中聲明的任何變量都會被添加到函數的執行上下文中。

將要添加的第一個變量是函數的參數,在本例中為 x 。

添加函數參數

現在,我們移至下一行並將 result 存儲在 execution context 中。

存儲結果

在下一行,用了 return 關鍵字來標記函數的結束。我們從調用棧中彈出 addOne() ,並給 output 賦值為4。

所以首先從 call stack 中彈出 addOne 。

從調用棧彈出

現在是最後一步,將值 4 分配給 output 變量。

最後一步

與上面類似,我們將標籤 output 發送到內存,但還沒有值,因為我們必須運行函數。

保存函數標籤

有趣的來了!接下來執行 addOne 函數。

當一個函數被執行時,它被添加到 call stack (調用棧)中。調用堆棧的底部總是有 global / main ,我們現在將 addOne(3) 入棧。

調用堆棧

我們還為該函數創建一個 execution context (執行上下文)。函數中聲明的任何變量都會被添加到函數的執行上下文中。

將要添加的第一個變量是函數的參數,在本例中為 x 。

添加函數參數

現在,我們移至下一行並將 result 存儲在 execution context 中。

存儲結果

在下一行,用了 return 關鍵字來標記函數的結束。我們從調用棧中彈出 addOne() ,並給 output 賦值為4。

所以首先從 call stack 中彈出 addOne 。

從調用棧彈出

現在是最後一步,將值 4 分配給 output 變量。

每天都會有更新看過的朋友可以點波關注,Java學習路線和優質資源評論或後台回復「Java」獲取。



完成!

就是這些了!我希望這能夠演示 JavaScript 代碼是如何逐步執行的。在本文中提到了 call stack (調用棧)和 execution context (執行上下文),將來我們將會更深入地研究它們。

關鍵字: