[JS] Object
備註
Change Log
- 2023:Initial version
- 2026/01/06:Fix code examples and refine explanations
取 key
Object.keys,取出物件的鍵。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2023-10-08'
}
const key = Object.keys(bookInfo)
console.log(key) // ['name', 'author', 'category', 'date']
取 value
Object.values,取出物件的值。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2023-10-08'
}
const value = Object.values(bookInfo)
console.log(value) //['Hogwarts professors', 'Jeremy', 'Fanfiction', '2023-10-08']
屬性刪除
delete,刪除一條屬性。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2023-10-08'
}
delete bookInfo['date']
console.log(bookInfo) // {name: 'Hogwarts professors', author: 'Jeremy', category: 'Fanfiction'}
迭代
for-in,可以視作物件的迴圈。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2023-10-08'
}
for(const item in bookInfo){
console.log(item)
}
// name
// author
// category
// date
複製
淺拷貝 (Shallow Copy)
...,最常見的淺拷貝用法。
注意
關於淺拷貝,要特別注意它對於深層的內容會有傳址的問題。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2023-10-08'
}
const copy = {...bookInfo}
{...obj1, ...obj2},其實就是...的衍伸,這是合併物件的一個方法。{...obj1, ...obj2}會建立一個新物件,並以後者的屬性覆蓋前者同名的屬性。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2024-01-01'
}
const newObj = {...bookInfo, ...obj2}
console.log(newObj)
// {
// name: 'Hogwarts professors',
// author: 'Jeremy',
// category: 'Fanfiction',
// date: '2024-01-01',
// author2: 'Joanna',
// job: 'designer'
// }
assign,也是淺層複製,也可以用在合併複數物件。
提示
Object.assign 的特性用白話講有兩點:
- target object (第一個參數) 原本沒有的屬性,會被新增 (來源自 source object,亦即第二個參數)。
- target object 原本已存在的屬性,會被 source object 的值覆蓋
這兩個特性有時在開發時有奇效。
主要體現在我們想避免替換整個物件導致 reference change 引起各種非預期的問題。
舉例來說,我們在 vue 開發時,假設 parent component 有個 form,它是個 reactive 物件,我們夠過 props 給內部的 child component,然後 emit 接收 child component 傳回來的修改值,這時候我們就可以利用 Object.assign 把 parent component 的 form 物件更新掉,而不是整個重新賦值,來避免一些諸如「畫面顯示正常,但在某些初始互動時短暫讀到 null 或舊資料」。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2023-10-08'
}
const obj2 = {
author2: 'Joanna',
job: 'designer',
date: '2024-01-01' // 注意這裡會覆蓋原本的 date 屬性
}
Object.assign(bookInfo, obj2)
console.log(bookInfo)
// {
// name: 'Hogwarts professors',
// author: 'Jeremy',
// category: 'Fanfiction',
// date: '2024-01-01',
// author2: 'Joanna',
// job: 'designer'
// }
注意
結果乍看之下會跟 {...obj1, ...obj2} 一樣,可能會想說那這樣寫更簡單不好嗎?
但其實他們有個非常巨大的差異在於 Object.assign 是對原物件進行修改且不變動 reference,而展開運算子則是建立一個全新的物件,這 reference 是一定會改變的。
深拷貝 (Deep Copy)
JSON.stringify與JSON.parse,這是一種常見但有限制的深拷貝手法,原理是先將物件序列化為字串,再反序列化成全新的物件,藉此切斷 reference。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2023-10-08'
}
const deepCopyBook = JSON.parse(JSON.stringify(bookInfo))
deepCopyBook.author = 'Joanna'
console.log(deepCopyBook)
console.log(bookInfo)
structuredClone,這是較新的深層複製方法,功能與JSON.stringify+JSON.parse類似,但支援更多資料類型 (如 Date、Map、Set 等)。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2023-10-08'
}
const deepCopyBook = structuredClone(bookInfo)
deepCopyBook.author = 'Joanna'
console.log(deepCopyBook)
console.log(bookInfo)
備註
structuredClone 雖說較新,但他的概念其實存在一段時間了,只是在大概 2021 年才正式成為通用的 web api。
這背後原因有包括那個被大家嘲笑的 IE 瀏覽器的退場,也有 JSON.stringify 與 JSON.parse 的限制性讓大家需要一個更好的解決方案。
查詢
property in Obj,這是用來查詢某個屬性是否存在於物件中。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2023-10-08'
}
console.log('author' in bookInfo) // true
hasOwnProperty,同樣也適用在查詢某個屬性是否存在於物件中。
console.log(bookInfo.hasOwnProperty('author')) // true
注意
in 會檢查原型鏈上的屬性,hasOwnProperty 只檢查物件自身屬性,實務上更安全。
- 可選串聯,新語法,對於深層不存在的屬性會回傳
undefined而不會中斷程式碼運作。
console.log(bookInfo?.author?.name) // undefined
Object to Array
Object.entries,這是把物件轉成陣列的方法。如果要把陣列轉成物件可以用Object.fromEntries。
const bookInfo = {
name: 'Hogwarts professors',
author: 'Jeremy',
category: 'Fanfiction',
date: '2023-10-08'
}
const arrBookInfo = Object.entries(bookInfo)
console.log(arrBookInfo)
// [[ 'name', 'Hogwarts professors' ], [ 'author', 'Jeremy' ], [ 'category', 'Fanfiction' ], [ 'date', '2023-10-08' ]]
const objBookInfo = Object.fromEntries(arrBookInfo)
console.log(objBookInfo)
// {name: 'Hogwarts professors', author: 'Jeremy', category: 'Fanfiction', date: '2023-10-08'}
Reference
- JavaScript 大全 (第七版) / David Flanagan / 歐萊禮出版
- 帶你無痛提升 JavaScript 面試力 / 卡斯伯 / 博碩出版
- JS - Object 物件基本操作