iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 3
1

一路上感謝各位讀者們的支持和回饋。
本 30 天系列文目前已經將篇幅重新整理、編纂成冊。
《JavaScript 概念三明治》在天瓏書局上架囉!
喜歡這個系列,想閱讀更詳細原理說明的讀者可以參考:
https://www.tenlong.com.tw/products/9789864347575

https://ithelp.ithome.com.tw/upload/images/20190918/20106580DNhAZIQ7hg.jpg

這個章節我們會直接介紹幾個專有名詞,包括前一章節提到的執行環境,加上執行堆疊,如果想要了解後面的提升、範疇等觀念,這些概念都是必要的,在後面的章節也會不斷被提到。

Outline

  • 執行環境
  • 執行堆疊

執行環境 ( Execution Context )

在前面提到直譯語言必須依賴環境才能被執行,在 JavaScript 裡面,提供這個環境的工作就是由 JavaScript 引擎來擔任。所以當我們說「瀏覽器執行/讀了你的 JavaScript 程式碼之後出現了錯誤」,其實並不真的是瀏覽器去讀你的程式碼,而是身為瀏覽器一部分的 JavaScript 引擎在做這件事。上面提到,能夠讓程式碼被執行的環境也被稱為「執行環境( Excution Context )」。

執行環境是一個抽象的概念,概括地來說,任何你JS 程式碼被執行、讀取的地方,像是 function 裡、甚至全域 ,都可以是執行環境。執行環境可以分為以下幾種:

  1. 全域執行環境 ( Global Ex. Context ) : JavaScript 預設的執行環境,不在任何函式裡面的程式碼就是在全域執行環境內,這個執行環境會做幾件事情:
    1. 創造全域環境(全域物件),(在瀏覽器裡面是 window ,在 Node.js 內是 global )
    2. 創造 this 物件,並將其指向這個全域物件,你可以打開瀏覽器的 console 並把 this 的值印出來試試看,關於 this 的指向在後面會提到。
    3. 記憶體指派流程(後面會提到)

https://ithelp.ithome.com.tw/upload/images/20190918/20106580nXss28IclV.jpg

https://ithelp.ithome.com.tw/upload/images/20190918/20106580KkRJpXgNdb.png

  1. 函式執行環境( Functional Ex. Context ): 每當一個函式被呼叫,一個全新的執行環境也會跟著被創造出來,這也代表 JS 已經開始解析你的程式碼並執行。函式執行環境產生時做的事情差不多,差別是不會產生全域物件,而相對的會在函式內產生 argument 物件,內容是執行階段時函式引數的內容。每個函式都有屬於自己的執行環境,但是只會在函式被呼叫的時候才會產生,這種執行環境可以同時存在好幾個。

  2. eval 函式內的執行環境:在 eval 函式內可以透過字串的方式去執行 JavaScript Code ,但是因為 eval 函式現在已經不常被使用,普遍也不被推薦使用,這邊就先不細提,想知道為什麼不被推薦,可以搜尋關鍵字「Eval is evil.」。

執行堆疊 ( Execution Stack )

上面我們提到,每當函式被呼叫時,就會產生對應的執行環境,而當函式裡有另一個函式被呼叫時,執行環境是按照什麼順序被產生的? JavaScript 使用後進先出的「堆疊」結構,依序來儲存隨著函式宣告所產生的執行環境。

各位應該都看過全面啟動吧?主角們為了完成任務不斷深入更下一層的夢境,而在每一層都有必須達成的目標,之後才能夠返回上一層,否則任務就會失敗。今天提到的堆疊其實是類似的概念,我們把「進入夢境」的動作對應到「函式呼叫」。

而到了下一層新的夢境,則呼應「產生執行環境」。你可以在裡面做任何你想做的事情,做完之後 return 回到上一層函式。放心,除非你喝醉了,否則寫 JS 是不會讓你進入混沌狀態的。讓我用一段程式碼來舉例,看看執行環境是如何被產生並且堆疊的:

let movie = 'Inception'

function firstLayerDream(){
			return secondLayerDream()
}

function secondLayerDream(){
			return thirdLayerDream()
}

function thirdLayerDream(){
			return 'Mission Complete.'
}  

let result = firstLayerDream()
  1. 當第一個位在全域的函式 firstLayerDream 被呼叫的時候,專屬的執行環境就產生了。
  2. 並且裡面的程式碼馬上就被「執行」(也就是開始被解析),直到碰到 return 關鍵字才會結束並離開這個執行環境。
  3. 隨著裡面的函式呼叫,第二層、第三層,的執行環境也被創造在裡面,一樣要等到 return ,才會結束並離開。

於是就有了這樣子的先後關係順序:

https://ithelp.ithome.com.tw/upload/images/20190918/20106580Cp4rvwMKBR.jpg

「堆疊」本身其實是一種資料結構,在堆疊裡面,某個元素之上如果還有有其他元素就無法被取出,因此有了「先進後出」的特性。如果你有吃過罐裝的品客應該可以很輕易知道我在說什麼,想想看,你沒辦法直接吃最底部的洋芋片對吧!

https://ithelp.ithome.com.tw/upload/images/20190918/20106580IZZcuynRg0.jpg

總結

今天稍微介紹了幾個非常重要的專有名詞,目前為止都還沒有進入 JS 語法的範疇,但這些觀念對於接下來的內容理解至關重要,請讀者一定要確定了解再往下,別擔心,如果有不理解的,隨時可以透過無線電聯絡我。


上一篇
JS 原力覺醒 Day02 - JavaScript V8 引擎
下一篇
JS 原力覺醒 Day04 - Function Scope / Block Scope
系列文
JavaScript 原力覺醒 - 成為絕地武士之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言