整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
[JS奇怪的世界]No.4 執行環境:創造與提升
前言
這章節將會講解到 JavaScript 中一個非常詭異的東西,那就是「創造與提升」而這部分也是許多人常搞不清楚的地方。
創造與提升
首先我們先挪用上一章節的範例程式碼 ↓
1 | |
可以看到我建立了一個全域變數及全域函數,而函數裡面寫了 console.log(b),這可以幫助我們在控制台 (console) 顯示資料的一個語法。
接下來我們要試著執行這些程式 ↓
1 | |
預期結果應該會看到 Hello World! 及 Tom。

果然與我們所預期的一樣。
那接下來如果我將將 console.log(a); 及 say(); 放在最前面會發生什麼事情呢?
1 | |

一般來講其他程式碼會直接錯誤 (Error),因為執行順序有問題,但是在 JavaScript 並不會跳出錯誤,而是回傳給你一個值 undefined,我們先不談 Undefined 是什麼。
那在 JavaScript 真正的執行狀況是怎樣?讓我們拆開來講,首先 JavaScript 會進入兩階段 ↓
- 創造模式
- 賦值模式
當 JavaScript 進入創造模式後,它會先將變數及函數找出來,然後提升創造,就像這樣子 ↓
1 | |
然而在創造變數 a 之後由於這個時候的 a 並沒有值,所以 JavaScript 在「預設執行環境」時,就會給 a 賦予一個特別的關鍵字,而這個特別的關鍵字,就是 undefined,那這個狀況又稱為 Hoisting (提升)。
所以在程式碼完整來看就是這樣子
1 | |
那 ‘Hello World!’ 什麼時候才會賦值呢?讓我們從範例程式碼來 ↓
1 | |
也就是因為這個原因才導致 a 出現 undefined 的原因,但是要注意提升 (hoisting) 這兩個字常常被誤會,並不是代表真的將程式碼被移動到最前面,程式碼是並沒有任何改變的,這只是 JavaScript 的一種特別的狀況。
那總和一下前面即到現在的章節觀念,一般來講 JavaScript 有分兩階段 ↓
- 創造階段 (creation,也就是建立執行環境)
- Global Object(window)
- this
- 外部環境
- 提升階段 (hoisting)
- 變數
- 函數
這邊的重點一樣在於「並不是代表真的將你的程式碼移動到最前面」,只是「編譯器」在執行時會將變數與函數預先建立出來,但是要注意一件事情已經執行的函數會「預先占用記憶體」,這也是為什麼人家講過多得執行函數會導致效能較差。
而變數會因為 Hoisting 特性而出現這種特別狀況,但是因為 a 還沒有被賦予值,直到它被執行它才會知道它現在應該是什麼值,而這時候 JavaScript 會預設給與它一個值,也就是 undefined,直到編譯器執行 a = 'Hello World!',這時候的 a 才會變成 Hello World,讓我們來試試看吧 ↓
1 | |
那結果呢?

我們可以發現第二次執行的console a,出現 Hello World,但第一次的console 卻是 undefined,我們試著拆開來分析就會變成這樣子。
1 | |
所以簡單來講所有在 JavaScript 中的變數一開始都是被設定成 undefined,而函數則是設定好並存入記憶體中,這章節我們理解到程式碼並不會立刻轉換成電腦可以懂得指令,而是透過「編譯器」進入幾個階段來處理(創造與提升)階段再轉換成電腦可以懂得指令。
補充資料
關於 hoisting 相關資料也可以看六角學院的共筆文件
當然也可以參考我之前所撰寫的Javascript中的hoisting
圖源
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ