iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 14
0
Modern Web

JavaScript Note系列 第 14

Call Stack 呼叫堆疊

  • 分享至 

  • xImage
  •  

在JavaScript中,函式是邏輯的集合區塊,也是執行的基本單元,我們可以使用函式將邏輯包裝重複使用,為特定運算設計出不同的功能。

如果單一任務執行需多個步驟方能完成,就需要多個函式協同運作,A函式呼叫B函式,B函式再呼叫C函式,當函式完成任務後,程式必須返回該函式被呼叫的位置。

那JavaScript引擎是如何確認整個流程的,以及它是如何知道函式結束後該返回哪個位置?

JavaScript的程式依執行環境就跟之前介紹變數一樣,分為兩種:全域程式與區域程式。
全域程式,在函式之外執行;區域程式,在函式之內執行。

執行環境也有分兩種,全域執行環境與區域執行環境。
全域執行環境只有一個,就是JavaScript程式一開始執行的時候建立的,而區域執行環境則是函式被呼叫執行時,所建立的,每個函式都會建立獨立的區域執行環境。

瀏覽器解析JavaScript是以單執行緒(single threaded)的方式進行。意思是,一次執行一個指令或函式。每個函式被呼叫時,會停止當前的執行環境(有可能是全域或區域),然後建立屬於該函式的區域執行環境,進入函式內部的程式碼進行運算。當該函式完成任務後,它的執行環境會被移除,然後回到原本呼叫該函式的執行環境中。

JavaScript引擎使用了一個方法追蹤執行其過程,執行環境堆疊(execution context stack)或呼叫堆疊(call stack)。

我們來看看實際的運作過程。

function getSum() {
    return 1 + getValue();
}
function getValue() {
    return 2;
}
let sum = getSum();
  • 一開始執行,會從全域執行環境開始,函式以外的程式碼,執行在全域執行環境中,所以目前只有全域執行環境在呼叫堆疊中。
  • 我們定義了2個函式。請注意,定義函式的過程不會執行函式,只有呼叫才會執行函式。
  • 首先呼叫getSum( ),由於JavaScript一次只會執行一段命令,所以全域環境的程式會暫停執行,然後建立getSum( )的區域執行環境,並將此環境放置於呼叫堆疊的頂部,此時有2個執行環境在呼叫堆疊中。
  • 在getSum( )中呼叫getValue( )。同樣地,暫停了getSum( )執行環境,並建立getValue( )執行環境,然後放置呼叫堆疊的頂部,此時有3個執行環境在呼叫堆疊中,由上而下依序是getValue( )、 getSum( )、全域執行環境。
  • getValue( )回傳結果後任務完成,其執行環境從呼叫堆疊移除,回到呼叫getValue( )執行環境,也就是getSum( )。
  • 當getSum( )完成任務後,也一樣其執行環境從呼叫堆疊移除,又再次回到最初的執行環境,全域執行環境。

以上就是執行環境在呼叫堆疊中的追蹤過程。請記住,JavaScript引擎一次只能執行一個函式或指令。
或許你會有疑問,那非同步呢?這種看似一次可以同時執行多個指令的方式,但其實在呼叫堆疊中還是以同步的方式進行,關於同步/非同步,之後會另開篇幅討論。


上一篇
一級函式 & 函式應用
下一篇
Scope 作用域
系列文
JavaScript Note31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言