---
# System prepended metadata

title: 變數
tags: [JavaScript]

---

---
tags: JavaScript
---
# 變數

由於網頁程式中會執行大量的程式腳本，不論你分割開來在不同的檔案中，最終在 script 標籤引入或是打包後都會變成共享同一個全域範疇，這時若發生非預期的 hoisting 或是全域污染，其導致的錯誤將會變得相當顯著，並且難以 Debug。

`const` 和 `let` 都是 **block-scoped**，也就是僅在限定的 `{}` function 內有效。

```javascript
if (true) {
  const a = 0
}
console.log(a)
// ReferenceError: a is not defined
```

## `const`

`const` 用於宣告**固定不變的常數**，變量指向**記憶體的位址不可以變動**，改變其值時會跳錯：

```javascript
const a = 1
a = 2
// TypeError: Assignment to constant variable.
```

但若其變數為 Array 或是 Object，在修改內容時並不會跳錯，因為這兩種都是屬於 reference type，所以變化的是內容時，本身的位置沒有改變，就不會跳錯。

```javascript
const a = [1, 2]
a.push(3)
// [1, 2, 3]
a = [4, 5, 6]
// TypeError: Assignment to constant variable.
```

## `let`

為何要使用 `let` 而非 `var` ？

1. `var` 的作用域 scope 比 `let` 還要大，蛋越大跨出步伐時越容易扯到蛋。

   ```javascript
   for ( var i = 0 ; i < 3 ; i++ ) {
	   setTimeout( () => { console.log(i) }, 1000 )
   }
   // 3 3 3 想不到吧
   ```
   
   `setTimeout` 會去註冊一個 callback function，1 秒後執行。在 scope 沒有管控好的狀況下，loop 裡頭的異步事件會去註冊起來，且使用 var 宣告的變數仍然會直到 i = 3 時才停止，並在一秒之後，分別被印出這些奇妙的東西。

## 參考資料

 - [Learn JavaScript in Y minutes](https://learnxinyminutes.com/docs/javascript/)
 - [JavaScript: Understanding the Weird Part](https://pjchender.blogspot.com/2017/06/javascript-understanding-weird-part.html)