做者:Paul Ryan翻譯:瘋狂的技術宅javascript
原文:https://alligator.io/js/threa...前端
未經容許嚴禁轉載java
這是研究 JavaScript 內部工做方式的系列文章的第一篇。我會盡力使它變得有趣,而且不讓你感到厭煩,由於我知道這些東西有時會變得很是乏味!程序員
想象一下,飛行員知道是飛機怎樣飛行的,而咱們天天運行 JavaScript 代碼,但知道它是如何運行嗎?面試
先讓咱們敲出一些簡單的 JavaScript 代碼:segmentfault
const num = 3; function addOne(x) { const result = x + 1; return result; } const output = addOne(num);
上面的代碼沒什麼讓你值得興奮的,可是能夠很好地幫助咱們演示執行線程。服務器
當執行 JavaScript 時,代碼會逐行(單線程)執行,所以在咱們的代碼中,要被執行的第一行是:微信
const num = 3;
下一個問題是,執行這行代碼會發生什麼? num 存儲在哪裏?多線程
num
存儲在全局內存/執行上下文中,看起來像這樣:框架
而後進入下一行:
function addOne(x) {
請務必注意,咱們在這裏聲明瞭一個函數,可是還不執行。所以,咱們將函數名稱與整個函數的值一塊兒存儲。
上面的 - f -
是整個函數的簡寫。
如今轉到下一行,有人可能認爲下一行是函數的主體,可是因爲咱們僅聲明函數而不是運行它,所以要運行的下一行是:
const 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
變量。
就是這些了!我但願這可以演示 JavaScript 代碼是如何逐步執行的。在本文中提到了 call stack
(調用棧)和 execution context
(執行上下文),未來咱們將會更深刻地研究它們。