Shallow VS Deep Copy 淺拷貝與深拷貝
簡單說
淺拷貝 只是 傳址
(by reference) 或 拷貝到第一層,還是會受到 來源 修改的連動影響; 深拷貝 拷貝的目標將會是獨立的個體,不會與來源有任何連動。
Shallow copy 淺拷貝
拷貝後目標 局部或全部都為 傳址 by reference
,會受到 來源資料 連動修改的影響。
=
賦值
copyObj
會受到 obj
修改的連動影響
js
let obj = { id: 1 }
let copyObj = obj
// 修改屬性
obj.id = 9
console.log(obj) // {id: 9}
console.log(copyObj) // {id: 9}
Object.assign
僅有第一維有完全 復製 ,第二維之後都是 傳址 by reference
,會受到修改連動影響。
js
let obj = { id: 1, obj2: { id: 2 } }
let copyObj = Object.assign({}, obj)
// 第一維修改
obj.id = 999
console.log(obj.id) // 999
console.log(copyObj.id) // 1
// 第二維修改
obj.obj2.id = 999
console.log(obj.obj2.id) // 999
console.log(copyObj.obj2.id) // 999
Spread Operator 展開運算子
其實是跟 Object.assign
完全一樣的能力,只有第一維是完全不受到連動影響。
js
let obj = { id: 1, obj2: { id: 2 } }
let copyObj = { ...obj }
// 第一維修改
obj.id = 999
console.log(obj.id) // 999
console.log(copyObj.id) // 1
// 第二維修改
obj.obj2.id = 999
console.log(obj.obj2.id) // 999
console.log(copyObj.obj2.id) // 999
Deep copy 深拷貝
拷貝後目標 完全不受到 來源資料 修改連動的影響且獨立運作。
JSON 字串化與解析還原
這個方法,是將物件轉換成單純的 字串 使其不具有 傳址 by reference
特性,再轉換為原本的 物件 型態,所有屬性都會是另外的記憶體,不受修改連動影響。
js
let obj = { id: 1, obj2: { id: 2 } }
let copyObj = JSON.parse(JSON.stringify(obj))
// 第一維修改
obj.id = 999
console.log(obj.id) // 999
console.log(copyObj.id) // 1
// 第二維修改
obj.obj2.id = 999
console.log(obj.obj2.id) // 999
console.log(copyObj.obj2.id) // 2
注意
這個方法僅適用於沒有 函式 屬性的物件格式,字串化的物件是無法還原 函式 的。
缺點
- 無法拷貝
函式
- 無法拷貝
原型鏈
structuredClone 深拷貝
這是最新用來處理「深拷貝」的原生語法,如果物件結構是較大較復雜的情況,使用 structuredClone
效能與速度會更優於 JSON.stringify
。
特點
- 不可拷貝函式
- 不保留原型鏈
語法
structuredClone
本身會回傳拷貝後的物件。
structuredClone(<將拷貝的物件>
)
js
const obj = {
id: 1,
name: 'naiky',
data: {
age: 37,
},
}
// 深拷貝
const strterObj = structuredClone(obj)
注意
當拷貝 function
、Error
、DOM
,會報錯 Uncaught DOMException: Failed to execute 'structuredClone' on 'Window':