深入理解 JavaScript 的型別操作與陣列變異行為
2025-06-26 02:10:23
## 請問以下程式碼執行結果是什麼?
```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
點擊複製文章連結