# **Hoisting**
看了很多文章說明,但還是沒有很懂Hoisting的基本概念,想自己梳理順過一次把理解的內容整理出來,再麻煩大家來找碴。
在學JavaScript時,很常耳提面命**宣告記得擺在前面**,主要是因為變數、函式在**宣告後會先建立一個記憶體空間**,等到要執行時再將值、函式放入,養成這樣的習慣就能避免一些錯誤資訊的出現。但是不這麼做呢?有時候程式還是跑得動,這時就會遇到Hoistng的問題!
Hoistng的概念以下簡單一句話輕鬆帶過,但是細細咀嚼發現疑問一直冒出來。
> *Hoistng是JavaScript將**宣告**移到頂端的默認行為。*
*在JavaScript中,變數可以在使用後宣告。換句話說,變數可以在宣告之前使用。—W3school*
>
### 變數與Hoisting
當程式中完全沒有任何宣告,直接執行變數,會以下出現錯誤訊息「carName is not defined」,**尚未被定義**。
```javascript=
console.log(carName);//出現Uncaught ReferenceError: carName is not defined
```
---
> *JavaScript **僅提升宣告**的部分,而不是初始化。如果在使用該變數後才宣告和初始化,那麼該值將是 undefined。—MDN*
>
如果在`console.log()`後進行宣告,並不會跳出錯誤而是會出現`undefined`。表示現在carName這個變數在記憶體中有個位置,只是目前沒有值。
console.log(carName);
var carName = "Volvo"
由於程式是由上至下一行一行慢慢跑,所以上圖在執行時,因為Hoisting特性把變數carName**宣告**提升到最前面,注意只有宣告,初始化(賦值”Volvo”)的部分並不會一同提升,所以可以理解上圖程式跑的邏輯如下:
```javascript=
var carName;//宣告 //undefined
console.log(carName);//undefined
carName = "Volvo";//初始化、賦予值
```
---
> *Hoisting也適用於其他型別和變數。變數可以在宣告之前進行初始化和使用。但如果沒有初始化,就不能使用它們。—MDN*
>
```javascript=
//#範例一
var x = 1; // 初始化 x
console.log(x + " " + y); // '1 undefined'
var y = 2;
//#範例二
var a = 1; // 初始化 a
var b; // 宣告 b
console.log(a + " " + b); // '1 undefined'
b = 2; // 初始化 b
//#範例三
var c = 1; // 初始化 c
d = 2; // 初始化 d
console.log(c + " " + d); // '1 2'
var d; // 宣告 d
```
範例一中,y的宣告及初始化都在`console.log`之後才,宣告因hoisting提前可以使用,但尚未初始化所以出現`undefined`,範例二的b其實就是y的程式運行邏輯。再來看到範例三,如果初始化是在`console.log`之前,宣告雖然在後面但會因為hoisting而提前,且d已經初始化,所以`console.log`可以順利顯示「1 2」。
關於hoisting還有temporal dead zone、函式提升等觀念,之後有時間再補上。