# 何謂 hoisting(向上提升)?以 let、const、var、function 為例
提升(Hoisting)是 JavaScript 將宣告移至頂部的默認行為。
然而,提升一詞可能會引起誤解:例如,提升看起來是單純地將變數和函式宣告,移動到程式的區塊頂端,然而並非如此。變數和函數的宣告會在編譯階段就被放入記憶體,但實際位置和程式碼中完全一樣。
在執行任何程式碼前,JavaScript 會把函式和宣告放進記憶體裡面,這樣做的優點是可以在程式碼宣告該函式之前使用它。
例:
```javascript=
var name = "劉德華";
console.log(name) //正常輸出 "劉德華"
console.log(old); //Uncaught ReferenceError: old is not defined
console.log(star); //undefined
var star = "港星"
```
一般在宣告變數並賦值後可以用log呼叫出來,
如果沒有宣告變數直接呼叫系統就會報錯,但是神奇的是...
先呼叫"之後"再用var宣告變數卻不會報錯,而是輸出undefined,這就是var的提升效果。
## 只有宣告會被提升
雖然javaScript會有提升效果,但是他只有相宣告提升,並不會將賦值提升。
拿剛剛的例子來說:
此一段程式僅僅是輸出undefined,我們有在變數中的賦值沒有拿來用到。
```javascript=
console.log(star); //undefined
var star = "港星"
```
在JS中的提升可以想像成這樣,提升後閱讀是
1. 宣告star
2. 呼叫star
3. 賦值給star
因此在呼叫前只有宣告並沒有賦值,系統只會覺得你沒有賦值而已所以不會報錯
```javascript=
var star;
console.log(star);
star = "港星";
```
## let 與 const
用 let 或 const 宣告的變量和常量不會被提升!
例子:雖然先呼叫之後有宣告,但是並不會出現undefined的訊息
```javascript=
console.log(Domi); //Uncaught ReferenceError: Domi is not defined
let Domi = "柴柴";
console.log(Meow); //Uncaught ReferenceError: Meow is not defined
const Meow = "貓咪";
```
## 函式的提升
因為有提升的效果我們就可以在宣告函式前就使用他,優化了編寫程式的過程,不用每次都先宣告函式後才能在下方使用,更可以將函式套入其他函式中。
例如:
```javascript=
hardWork(); //因函式有提升效果,因此會執行
function hardWork(){
console.log("讀書");
console.log("練習程式")
console.log("工作")
relax();
}
hardWork();
function relax(){ //雖然後定義,但是被提升至上面所以可以正常寫入
console.log("睡覺")
}
// 讀書
// 練習程式
// 工作
// 睡覺
// 讀書
// 練習程式
// 工作
// 睡覺
go(); //但是函式運算式就不會提升
let go = function(){
console.log("gogo")
}
```
## 函式與變數
函數與變數之前也有不為人知的提升秘密...
例子:
如果照變量提升的方式來看的話會覺得是unfined,但是輸出的答案是 55。
```javascript=
function age(x){
console.log(x);
var x = 28;
}
age(55);
// 過程
function age(x){
var age = 55; //先提升參數的變量
var x;
console.log(x);
x = 28;
}
age(55); //因此輸出55
```
## 總結
* 變數宣告跟函式宣告都會提升
* 只有宣告會提升,賦值不會提升
* 函式裡面會傳進參數,並且放在最上面
* let與const宣告不會提升,會報錯
## 參考資料
[提升(Hoisting)](https://developer.mozilla.org/zh-TW/docs/Glossary/Hoisting)
[W3school](https://www.w3school.com.cn/js/js_hoisting.asp)
[我知道你懂 hoisting,可是你了解到多深?](https://blog.techbridge.cc/2018/11/10/javascript-hoisting/)
[淺談JS預解析](https://iter01.com/561971.html)