前言
今天課程談到了關於「全域執行環境」與「全域物件」,那麼這兩個東西又是什麼呢?首先我們需要了解到:
- 不論何時執行 JavaScript 程式,皆是在執行環境 (Execution Context)裡面執行
- 當我們第一次執行 JavaScript 時,會看到基礎的執行環境 被建立、執行
執行環境就像一個別人寫好的程式把正在執行的程式碼包裹在裡面內驗證、執行。
全域執行環境
前面提到的基礎執行環境,也可以稱為全域執行環境 (Global Execution Context),「全域」指可在區域裡、JavaScript 檔案裡、詞彙環境裡被取用。
全域執行環境創造了兩件事情:「全域物件 (Global Execution Object)」、「特殊的變數 this」
全域物件
還記得物件的解釋嗎,就只是 名稱 / 值 的組合,再帶入「全域」的概念
實際驗證
接下來我們可以開始寫一點程式碼測試看看,像是這樣:
- 什麼都不寫,並打開開發人員工具觀察,
這個時候其實已經做了這些事情:
- JavaScript 檔案被載入 > 語法解析啟動 > 沒寫任何程式碼,所以沒有被執行
但是 JavaScript 確實已經運行,執行環境已經被創造出來了,另外還有「全域物件」、「 this」,我們可以進行驗證,執行環境內有什麼?
- 直接輸入 this 看看
我們什麼都沒寫,為什麼會有這個 window 物件
因為 JavaScript 已經將執行環境建立,而執行環境可以決定現在這個 this 的值是什麼
那如果我們直接輸入 window 會怎麼樣? 我們會得到一樣的結果。
執行 JavaScript 時永遠會有一個全域物件
在瀏覽器的話就是 window ,如果再伺服器上執行 node.js 那結果會是得到 Global ,會是個不同的全域物件。另外,不同分頁的全域物件 window,雖然名稱一樣,但彼此是沒有關聯的。
每個分頁有自己的執行環境、全域物件。
整理一下目前的思緒,得出如下圖結論
讓我們把「全域 (GLOBAL)」再定義得更清楚一點:
原文是這麼寫的「Not Inside a Function」,在 JavaScript 中表示不再函式(Function)內,更直白一點「程式碼或者變數不再函式裡就是全域的」,讓我們直接來驗證。
1 | var a = 'Hello world'; |
至此,我們有了一個變數、函式,與之前不同的是,現在我們有程式碼了。而且變數 a 不再 b 函式裡,現在的情況是「全部的程式碼都不再函式裡」,讓我們觀察看看它們是不是「全域」的。
如紅框處,我們建立的變數 a
、函式 b
,如果不是在函式內建立,那麼這些東西就會與全域物件做連結,也就可以產生以下寫法,兩者是一樣的。
至此,本篇大致上到這裡結束,再利用圖片加深一下印象
還有一些事情沒有提到,像是「外部環境 (Outer Environment)」,意思就是說,當程式碼在函式內執行,這代表程式碼在函式內;當在程式碼在全域時,代表不是在函式內,此時就沒有「外部環境 」,因為這已經是最外層了,此時會是 null
,這樣講好像有聽沒懂,再來個例子:
1 | function b(){ |
猜猜這樣寫函式 b
會印出什麼?
答案是 1,為什麼?
原因很簡單,在 JavaScript 中,如果要呼叫一個在該「執行環境」中沒有的變數時,它會往它的「外部環境 」去找。
也就是說:
- 我們先宣告了全域變數 (
myVar = 1
),因此全域執行環境有了 (myVar = 1
) - 接著執行函式
a
,但這裡的myVar
不是全域變數,而是區域變數 (myVar = 2
) - 最後又執行函式
b
,但對函式 b而言並沒有變數myVar
,此時函式b
會從「外部環境 」尋找變數myVar
,也就是一開始宣告的全域變數 (myVar = 1
),而不會是函式 a的(myVar = 2
)
後記:
感覺自己又對 JavaScript 更了解了一點,不過瞭解這些專有名詞是有點想睡覺…,但是瞭解這些名詞其實有助於後續課程的學習,你必須知道這些名詞是什麼意思,才能理解講師再說什麼。另外外部環境我覺得是個蠻重要的東西,了解這個有助於避免掉一些鬼打牆的情況。