JavaScript 物件深入淺出重點整理
資料型別 (Data Type)
JavaScript 的型別主要分兩大類別,分別是原始型別 (Primitive type) 及參考型別 (Reference type)。
- Primitive type
- Boolean
- Null
- Undefined
- Number
- String
- BigInt
- Symbol(於 ECMAScript 6 新定義)
- Reference type
- Object: Primitive type 以外的都屬於 Object 型別。例:
Object {}、Array []、Function ()。
- Object: Primitive type 以外的都屬於 Object 型別。例:
Primitive type 和 Reference type 都是 call by value。不一樣的是儲存的東西。結束!
有人會說 Reference type 是 call by reference 或 call by sharing (這個比較符合我的意思和理解)。但是請先去看這篇:值 (value)、指標 (pointer/address)、參考 (reference)。
Primitive types call by value
1 | let x = 5, y = 10; |
call by value:將 x, y 的值 copy 一份給 a, b。

swap() 執行完畢後 x, y 不會互換,a, b 會互換。

Reference types call by value
1 | let x = { name: "Jenifer" }, |
call by value:一樣將 x, y 的值 copy 一份給 a, b。但是,因為儲存的不是物件本身,而是物件的位址,所以有很多陷阱和地雷要注意。


swap() 執行完畢後 x, y 不會互換,a, b 會互換。


如果改成:
1 | let x = { name: "Jenifer" }, |
使用 物件名稱.屬性名稱 = 值 會在同樣的記憶體位址增加屬性。因為 b 和 x 儲存一樣的記憶體位址,所以印出和 x 相同的結果。

使用 const 還是可以對屬性修改
因為沒有修改儲存的記憶體位址,僅修改屬性,不會報錯。注意:物件中的屬性名稱只會唯一存在。
1 | const x = { name: "Jenifer" }; |
重新指定記憶體位址會報錯。

splice()、pop()、push() 屬於修改屬性的函式。
slice() 是回傳一個新的陣列的函式。
1 | function newStaff(obj) { |
利用 Object.keys() 淺層複製
The
Object.keys()method returns an array of a given object’s own enumerable property names, iterated in the same order that a normal loop would.
Object.keys() 回傳一個新的陣列,依序列舉出屬性名稱。
1 | const x = { |
注意:像是陣列的物件,有著任意 key 順序,使用 Object.keys() 會自動將其排序。
array-like object with random key ordering
1 | const fruits = { |
參考資料:
MDN Web Docs - Object.keys()
淺層複製
1. 展開運算子 (Spread Operator) { ...obj } 或 [ ...obj ]
淺層會有新的記憶體位址,但是深層的記憶體位址就一樣。改動新物件時會更動到舊物件,不是好的複製。
1 | const x = { |
2. 會回傳一個新物件、陣列的方法
a. Object.keys()、for-in loop。
b. 僅 Array: Array.map( x => x )、Array.filter(() => true) 等。
c. 僅 Object: Object.assign({}, obj) (array 也可以用,但會變物件)。對於 obj 來說 Object.assign({}, obj) 和 { ...obj } 基本上是一樣的。
深層複製
1. JSON.parse(JSON.stringify(obj))
1 | const x = { |
2. structuredClone(obj)
ECMAScript 2021 新提供了 structuredClone(),這是一個用於深層複製的內建函式。
1 | const newX2 = structuredClone(x); |
補充資料:
structuredClone()
Can I use structuredClone?
奇怪的物件
1 | let a = { |
從第六行可以看出來有 Hoisting 的特性,a.y 或是說 b.y 早就已經被創造好,被賦予 undefined。因此在第六行時,情況如下圖。

第八行 a 被賦予新物件。而 a = { name: "Mary" } 是表達式,會回傳 { name: "Mary" } ,因此 a.y 或是說 b.y 也被賦予新物件。

參考資料:
六角學院:JavaScript 常見考題破解:物件傳值?傳參考?