---
# System prepended metadata

title: 深入理解 JavaScript 的型別操作與陣列變異行為
tags: [JavaScript]

---

# 深入理解 JavaScript 的型別操作與陣列變異行為
> 為什麼 `const` 陣列還可以改？為什麼字串卻不能？


## 請問以下程式碼執行結果是什麼？

```js
let name = 'cindy'
name[0] = 'C'
console.log(name)
```

 A：你可能會直覺以為輸出 `'Cindy'`，但實際結果會是：

```
cindy
```

## 為什麼不能改變字串的內容？

因為 `string` 是 **原始型別（primitive type）**，它是 **不可變的（immutable）**。

在 JavaScript 中，原始型別（如 `string`, `number`, `boolean`）：

* 儲存在 **stack 記憶體中**
* 一旦建立後就不能修改
* 若要改變，只能「整個覆寫」

例如：

```js
let name = 'cindy'
name = 'C' + name.slice(1)
console.log(name) // 'Cindy'
```

## 那這段程式碼又會輸出什麼？

```js
let nameArray = ['alen', 'tim', 'kevin']
nameArray[0] = 'Alen'
console.log(nameArray)
```

A：

```
['Alen', 'tim', 'kevin']
```

這次成功改變了第一個元素的值，為什麼？

## 為什麼陣列可以改變內容？

因為陣列是 **參考型別（reference type）**：

* 儲存在 stack 的是「指向 heap 的參考（pointer）」
* 改變內容時，其實是**透過這個參考去修改 heap 記憶體的值**

這不違反 `let` 或 `const` 的限制，因為我們**沒有改變參考位置**，只是改了它所參考的內容。


## 那如果我用 `const` 宣告陣列，可以改變內容嗎？

```js
const color = ['red', 'blue', 'yellow']
color[0] = 'green'
console.log(color)
```

A：

```
['green', 'blue', 'yellow']
```

即使是 `const` 宣告的陣列，也**可以改變內容**！


## 那 `const` 到底保護了什麼？

`const` 保護的是：

> 🔒 **變數所綁定的參考記憶體位置（binding）不能被重新指派**

但它**沒有凍結 heap 中的值**。你仍可以透過這個參考去修改內容。

### 所以這會報錯：

```js
const color = ['red']
color = ['green'] // ❌ TypeError
```

但這是合法的：

```js
color[0] = 'green' // ✅ OK
```

### 開發上的實務建議：

> 在大多數情況下，你應該預設用 `const` 來宣告 array 和 object，這樣可以避免無意中重新賦值（例如函式中的重複設值或被覆蓋），讓你的 code 更有預測性與安全性。


## `array[3] = 4` 跟 `array.push(4)` 有什麼差別？

```js
const arr = [1, 2, 3]

arr[3] = 4
console.log(arr)

arr.push(5)
console.log(arr)
```

A：

```js
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
```

兩者都可以「新增元素」，但行為差異在於：

| 操作方式          | 說明                |
| ------------- | ----------------- |
| `arr.push(x)` | 將元素插入**最後一格**（自動） |
| `arr[n] = x`  | 插入**指定位置**，可能會跳號  |

若你這樣做：

```js
arr[10] = 'x'
```

你會得到一個 **稀疏陣列**：

```js
[1, 2, 3, 4, 5, <5 empty items>, 'x']
```

這在某些 JS 引擎會降低效能。


## 結語
> 觀察「變數的操作方式」是理解型別的另一個視角

* 若你改變變數的值，觀察是否會改變參考位置或內容
* 若它是原始型別，你只能用覆蓋方式重新賦值
* 若它是參考型別（array/object），你可以透過 pointer 改變內容


### 🔁 總整理：操作行為對照表

| 型別       | 是否 mutable | 是否可改內容 | 是否可重新賦值 (`const`) |
| -------- | ---------- | ------ | ----------------- |
| `string` | ❌ 否        | ❌ 否    | ❌ 否               |
| `array`  | ✅ 是        | ✅ 是    | ❌ 否（內容可改，參考不可換）   |
| `object` | ✅ 是        | ✅ 是    | ❌ 否（同上）           |




## 參考資料

* [MDN Web Docs - JavaScript Data Types and Structures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures)
* [MDN - Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
* [Udemy - The Web Developer Bootcamp 2025](https://www.udemy.com/course/the-web-developer-bootcamp/) by Colt Steele


