> For the complete documentation index, see [llms.txt](https://jack1in.gitbook.io/font-end/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jack1in.gitbook.io/font-end/2.-javascript/2.4-hoisting.md).

# 2.4 hoisting

**在JavaScript程式語言當中，它會自動幫你把你有宣告的變數、Function自動拉至最上方**

在 JavaScript 裡面，如果對一個還沒宣告的變數取值，會發生以下錯誤：

```
console.log(a)
// ReferenceError: a is not defined
```

會回傳`a is not defined`的錯誤，因為你還沒宣告這個變數，所以 JavaScript 也找不到這變數在哪，自然就會拋出錯誤。

可是如果你這樣子寫，神奇的事情發生了：

```
console.log(a) // undefined
var a
```

這種現象就叫做 hoisting，提升，在第二行的`var a`因為某種原因被「提升」到了最上面，所以上面的程式碼你可以「想像」成這樣：

```
var a
console.log(a) // undefined
```

再來還有一點要特別注意，那就是只有**變數的宣告會提升，賦值不會**，看看以下範例你就懂了：

```
console.log(a) // undefined
var a = 5
```

上面的程式碼你可以「想像」成這樣：

```
var a
console.log(a) // undefined
a = 5
```

#### 函式運算式不會被提升 <a href="#han-shi-yun-suan-shi-bu-hui-bei-ti-sheng" id="han-shi-yun-suan-shi-bu-hui-bei-ti-sheng"></a>

函式運算式（function expression）不會被提升。如下，foo 此時的值是 undefined，所以當執行 `undefined()` 就會得到 TypeError。而 bar 這個識別字是屬於 foo 的範疇的，所以在這裡會報錯 ReferenceError。

```
foo(); // TypeError
bar(); // ReferenceError

var foo = function bar() {
  // ...
};
```

### 重複宣告 <a href="#zhong-fu-xuan-gao" id="zhong-fu-xuan-gao"></a>

若函式和變數同名，則函式會優先；若同時有多個函式同名，則後面的會覆寫前面的宣告。

#### 範例 1：若函式和變數同名，則函式會優先 <a href="#fan-li-1-ruo-han-shi-he-bian-shu-tong-ming-ze-han-shi-hui-you-xian" id="fan-li-1-ruo-han-shi-he-bian-shu-tong-ming-ze-han-shi-hui-you-xian"></a>

範例如下，同名函式 foo 和變數 foo，由於函式優先，因此 `foo()` 得到 1 而非 `undefined()` 的結果 TypeError。

```
foo(); // 1

var foo;

function foo() {
  console.log(1);
}

foo = 2;
```

#### 範例 2：若同時有多個函式同名，則後面的會覆寫前面的宣告 <a href="#fan-li-2-ruo-tong-shi-you-duo-ge-han-shi-tong-ming-ze-hou-mian-de-hui-fu-xie-qian-mian-de-xuan-gao" id="fan-li-2-ruo-tong-shi-you-duo-ge-han-shi-tong-ming-ze-hou-mian-de-hui-fu-xie-qian-mian-de-xuan-gao"></a>

範例如下，三個同名函式 foo，最後一個 foo 會覆寫前面的宣告，因此得到 3。

```
foo(); // 3

function foo() {
  console.log(1);
}

function foo() {
  console.log(2);
};

function foo() {
  console.log(3);
}
```

### **let、const 不會有hoisting**
