一路上感謝各位讀者們的支持和回饋。
本 30 天系列文目前已經將篇幅重新整理、編纂成冊。
《JavaScript 概念三明治》在天瓏書局上架囉!
喜歡這個系列,想閱讀更詳細原理說明的讀者可以參考:
https://www.tenlong.com.tw/products/9789864347575
這個章節我們會直接介紹幾個專有名詞,包括前一章節提到的執行環境,加上執行堆疊,如果想要了解後面的提升、範疇等觀念,這些概念都是必要的,在後面的章節也會不斷被提到。
在前面提到直譯語言必須依賴環境才能被執行,在 JavaScript 裡面,提供這個環境的工作就是由 JavaScript 引擎來擔任。所以當我們說「瀏覽器執行/讀了你的 JavaScript 程式碼之後出現了錯誤」,其實並不真的是瀏覽器去讀你的程式碼,而是身為瀏覽器一部分的 JavaScript 引擎在做這件事。上面提到,能夠讓程式碼被執行的環境也被稱為「執行環境( Excution Context )」。
執行環境是一個抽象的概念,概括地來說,任何你JS 程式碼被執行、讀取的地方,像是 function 裡、甚至全域 ,都可以是執行環境。執行環境可以分為以下幾種:
函式執行環境( Functional Ex. Context ): 每當一個函式被呼叫,一個全新的執行環境也會跟著被創造出來,這也代表 JS 已經開始解析你的程式碼並執行。函式執行環境產生時做的事情差不多,差別是不會產生全域物件,而相對的會在函式內產生 argument 物件,內容是執行階段時函式引數的內容。每個函式都有屬於自己的執行環境,但是只會在函式被呼叫的時候才會產生,這種執行環境可以同時存在好幾個。
eval 函式內的執行環境:在 eval 函式內可以透過字串的方式去執行 JavaScript Code ,但是因為 eval 函式現在已經不常被使用,普遍也不被推薦使用,這邊就先不細提,想知道為什麼不被推薦,可以搜尋關鍵字「Eval is evil.」。
上面我們提到,每當函式被呼叫時,就會產生對應的執行環境,而當函式裡有另一個函式被呼叫時,執行環境是按照什麼順序被產生的? JavaScript 使用後進先出的「堆疊」結構,依序來儲存隨著函式宣告所產生的執行環境。
各位應該都看過全面啟動吧?主角們為了完成任務不斷深入更下一層的夢境,而在每一層都有必須達成的目標,之後才能夠返回上一層,否則任務就會失敗。今天提到的堆疊其實是類似的概念,我們把「進入夢境」的動作對應到「函式呼叫」。
而到了下一層新的夢境,則呼應「產生執行環境」。你可以在裡面做任何你想做的事情,做完之後 return 回到上一層函式。放心,除非你喝醉了,否則寫 JS 是不會讓你進入混沌狀態的。讓我用一段程式碼來舉例,看看執行環境是如何被產生並且堆疊的:
let movie = 'Inception'
function firstLayerDream(){
return secondLayerDream()
}
function secondLayerDream(){
return thirdLayerDream()
}
function thirdLayerDream(){
return 'Mission Complete.'
}
let result = firstLayerDream()
於是就有了這樣子的先後關係順序:
「堆疊」本身其實是一種資料結構,在堆疊裡面,某個元素之上如果還有有其他元素就無法被取出,因此有了「先進後出」的特性。如果你有吃過罐裝的品客應該可以很輕易知道我在說什麼,想想看,你沒辦法直接吃最底部的洋芋片對吧!
今天稍微介紹了幾個非常重要的專有名詞,目前為止都還沒有進入 JS 語法的範疇,但這些觀念對於接下來的內容理解至關重要,請讀者一定要確定了解再往下,別擔心,如果有不理解的,隨時可以透過無線電聯絡我。