Primitive vs Reference Data Types in JavaScript

Primitive vs Reference Data Types、Stack vs Heap、By Value vs By Reference、Shallow Copy vs Deep Copy

·

2 min read

credit Primitive vs Reference Data Types in JavaScript

1. Primitive Data Types

JavaScript 的 Primitive Data Types(原始數據類型) 是不可變的,並且直接存儲在 Stack(堆疊) 記憶體中。

主要的 Primitive 類型

  • String(字串)

  • Number(數字)

  • Boolean(布林值)

  • Undefined(未定義)

  • Null(空值)

  • BigInt(大數值)

  • Symbol(符號)

特性

  • 直接存儲在 Stack 記憶體中。

  • 傳遞時是 By Value(按值傳遞),即複製值的副本。

  • 不可變(Immutable),修改變數時實際上是創建新值,而非修改原值。

範例

let a = 10;
let b = a; // 複製值
b = 20;
console.log(a); // 10(a 不受影響)
console.log(b); // 20

2. Reference Data Types

Reference Data Types(引用數據類型) 是可變的,並且存儲在 Heap(堆記憶體) 中,變數實際上儲存的是該對象的引用(地址)。

主要的 Reference 類型

  • Object(物件)

  • Array(數組)

  • Function(函數)

  • Date(日期)

  • RegExp(正則表達式)

特性

  • 存儲於 Heap 記憶體,變數存放的是指向 Heap 內存的地址。

  • 傳遞時是 By Reference(按引用傳遞),即變數存儲的是對象的內存地址,而非值的副本。

  • 可變(Mutable),對變數的修改會影響到原始對象。

範例

let obj1 = { name: "Alice" };
let obj2 = obj1; // obj2 取得 obj1 的記憶體地址
obj2.name = "Bob";
console.log(obj1.name); // "Bob"(obj1 被修改了)

3. Stack vs Heap

Stack(堆疊)

  • 用於存儲 Primitive Data Types

  • 變數直接存儲其值。

  • 內存分配是自動的,當變數超出作用域時,自動釋放內存。

Heap(堆)

  • 用於存儲 Reference Data Types

  • 變數存儲的是對象的 內存地址,實際數據存儲在 Heap 中。

  • 需要手動管理內存,JavaScript 使用 垃圾回收(Garbage Collection) 來回收不再使用的對象。


4. By Value vs By Reference

By Value(按值傳遞)

  • 適用於 Primitive Data Types

  • 賦值時,會創建變數的副本,修改副本不會影響原始變數。

範例

let x = 100;
let y = x; // y 獲得 x 的值(複製)
y = 200;
console.log(x); // 100(x 不受影響)

By Reference(按引用傳遞)

  • 適用於 Reference Data Types

  • 賦值時,變數存儲的是內存地址,修改副本會影響原始變數。

範例

let objA = { value: 1 };
let objB = objA;
objB.value = 2;
console.log(objA.value); // 2(objA 被影響)

5. Shallow Copy vs Deep Copy

Shallow Copy(淺拷貝)

  • 只複製第一層的屬性,內部的引用類型仍然指向原內存地址。

  • 修改內部對象時,原對象也會受到影響。

淺拷貝方式

  • Object.assign()

  • 展開運算符 ...

範例

let obj1 = { name: "Alice", details: { age: 25 } };
let obj2 = { ...obj1 }; // 淺拷貝
obj2.details.age = 30;
console.log(obj1.details.age); // 30(原對象受影響)

Deep Copy(深拷貝)

  • 創建完全獨立的副本,所有層級的對象都會被複製。

  • 修改新對象不會影響原對象。

深拷貝方式

  • JSON.parse(JSON.stringify(obj))(不適用於函數和 undefined

  • structuredClone(obj)(最新的深拷貝方法,支援所有類型)

  • Lodash_.cloneDeep(obj)(推薦)

範例

let obj1 = { name: "Alice", details: { age: 25 } };
let obj2 = JSON.parse(JSON.stringify(obj1)); // 深拷貝
obj2.details.age = 30;
console.log(obj1.details.age); // 25(原對象不受影響)

6. 總結

類型存儲位置賦值方式影響原對象
Primitive Data TypesStackBy Value❌(不影響)
Reference Data TypesHeapBy Reference✅(影響)
Shallow CopyHeapBy Reference(部分複製)✅(影響內部引用)
Deep CopyHeapBy Value(完全複製)❌(不影響)

這篇文章詳細介紹了 JavaScript 的原始數據類型與引用數據類型的區別,並解析了 Stack vs Heap、By Value vs By Reference 以及 Shallow Copy vs Deep Copy,幫助你更好地理解 JavaScript 記憶體管理與數據操作方式。