---
# System prepended metadata

title: "⬆️向上提升\U0001F199\U0001F199\U0001F199"
tags: [Javascript, 六角學院, JS 直播班 - 2021 秋季班]

---

# ⬆️向上提升🆙🆙🆙
## 何謂 hoisting(向上提升)？以 let、const、var、function 為例

```javascript=
Fn("哈哈");

function Fn(str){
	console.log("這下你ＧＧ了吧！"+str);
}

// 印出"這下你ＧＧ了吧！哈哈" 為什麼執行後有印出來，
// 執行的時候不是還沒宣告嗎？

console.log(num)

var num = 45;

// 結果應該是 num is not defined吧。
// 結果居然是 undefined ！！

```

![](https://i.imgur.com/joDypsO.png)

>Javascript 執行的運作原理可以大致分成創造跟執行階段，
>JS 會分開做在程式開始時候，會先將函式與變數宣告到記憶體中，
>之後才會依序執行流程，但是只有宣告並不會進行賦值，
>所以可以看到上面案例 num 變數是 undefined 不是 not defined 也不是45。

```javascript=
// 那我們來看另外的案例
function show(num){
	var num;
	console.log(num);
	num = 0;
}

show(5)

// 照剛剛 hoisting 的概念 應該會印出 undefined 吧。
// 結果卻印出了 5 
```
![](https://i.imgur.com/IlGTPYa.png)

>在提升的過程中，傳入的參數也是會進行值得賦予，
>可以看成是
```javascript=
function show(num){
	var num = 5;
	var num;
	console.log(num);
	num = 0;
}
// 因為 hoisting 的緣故
// 中間執行的狀況變成
var num; // 參數 hoisting
var num;
num = 5;
console.log(num)

//最後還有一種情形
console.log(Fn)
var Fn;
function Fn(){}

// 結果印出了 ƒ Fn(){}
// function 也會 hoisting 優先權還比變數還高 😵‍💫
```
>function 的 hoisting 的權限高於變數，以便於如果沒宣告就不能使用，
>那將導致使用者必須將所有函式都寫在開頭，且函式也無法互相呼叫。
```javascript=
// 以下為函式互相呼叫的案例

function loop(n){
	if(n<5){
		calcFn(++n)
	}
}

function calcFn(n){
	console.log(n,n%2 ? "奇數": "偶數")
	loop(n)
}

loop(1)
// 2 '偶數' 3 '奇數' 4 '偶數' 5 '奇數' 
// 可以正確顯示出升冪並顯示奇數偶數
```
>所以 function 具備 hoisting 看起來必要性是必然的。

```javascript=
console.log(num)
let num
// 有兩種顯示錯誤 ReferenceError: num is not defined
// Cannot access 'num' before initialization 
// 如果在 node 高版本環境則會顯示這個

```
>let const看似不會，其實也會hoisting
```javascript=
// 這個案例就可以看出 let 也是有 hoisting 的機制
var num = 5;
function show(){
	console.log(num)
	let num
}
show()
// 結果沒意外應該是印出 5
// 結果卻印出了 ReferenceError: num is not defined

```
>可見得 let 也將 num 提升了，只是作用行為跟 var 不同，
>var 做的提升宣告的變數會被進行初始化為 undefined ，而 let const 則是
>不會進行初始化 undefined ，所以在賦予值之前呼叫則會報錯， Javascript 在
>提升後與賦予前的期間存在一個 TemporalDeadZone 的區域簡稱 TDZ
![](https://i.imgur.com/yE6CTF8.png =60%x)
```javascript=
// 案例
function calc(){
	var num1 = 5; //num3 的TDZ開始
	var num2 = 10;
	console.log(num3); // 報錯
	if(num2>num1){
		console.log(num2)
	}
	let num3 = 15; // num3 TDZ結束
}
calc()

```

## 寫在結尾
hoisting 確實的解決了 JS 上面 function 互相呼叫的問題，
而在名稱衝突發生時優先順序高到低為:
1. 函式宣告 function declaration
1. 函式參數 function arguments
1. 變數宣告 variable



### 參考資料
[提升（Hoisting）- MDN](https://developer.mozilla.org/zh-TW/docs/Glossary/Hoisting)
[D6 - 你不知道 Combo : 主菜 Scope 字彙環境](https://ithelp.ithome.com.tw/articles/10269077)
[[第十七週] JavaScript 進階：從 EC 來理解 Hoisting](https://yakimhsu.com/project/project_w17_advancedJS_02_Hoisting.html)
[我知道你懂 hoisting，可是你了解到多深？](https://github.com/aszx87410/blog/issues/34)

###### tags: `Javascript` `JS 直播班 - 2021 秋季班` `六角學院`