在ES6中擴展操作符(…)與Object.assign()中複製是淺拷貝,所謂的淺拷貝和深拷貝:
淺拷貝,是在拷貝過程中,遍歷時那部分爲對象/數組類型指向原來的地址。即修改其中任意的值,另一個值都會隨之變化
深拷貝,則是完全開闢新的內存地址。即將對象及值複製過來,兩個對象修改其中任意的值另一個值不會改變
1、淺拷貝
淺拷貝: 只做一個最外層的拷貝. 如果拷貝的對象是引用型數據類型,則意味着交出了內存地址,因而在淺拷貝成功的對象身上對引用型數據進行修改時,就會影響到 原來的拓本
let obj = {
a: 1,
b: [1, 2, {a:3}],
c: {a:3}
}
obj.c.a = 4
let obj1 = {
a: obj.a,
b: obj.b
}
obj1.b.push(1) // 切記不要
obj1.b = 123 這樣是重新賦值 不是改變原地址的對象
console.log(obj.b) //將會被改變
ES6方法:
let obj2 = Object.assign({},obj)
console.log(obj2) // {a: 1,b: [1, 2, {a:3}],c:{a:4}
let obj3 = {...obj}
conosle.log(obj3) // {a: 1,b: [1, 2, {a:3}],c:{a:4}
2、深拷貝
深拷貝: 裏裏外外全部拷貝,完全複製,保證引用型數據 依舊是引用型,但不拿地址,只模仿你的面,因此擴展上沒有問題,不會衝突
let obj1 = {
a: 1,
b: [1, 2, {a:3}],
c: {a:3}
}
//完全複製 完美複製 但是一個一個去複製,太麻煩啦 我們來一個專門深淺複製的函數
obj1.c.a = 4
let obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2) // {a: 1,b: [1, 2, {a:3}],c:{a:3}
自制深複製函數
1.需求 參數1傳入拓本 輸出拷貝品
let obj = { //拓本
a: 1,
b: [1,2,3,{a: "我"}],
c: {d: 5}
}
function extend (o1) {
var obj1 = {}
if (o1 instanceof Array) { //判斷對象是否是數組
obj1 = []
}
for(var key in o1){
var value = o1[key] // 拓本中的值
// value內還有引用型數據&& value不爲 null 則 需要對value這個對象 再進來 深拷貝一份 返回出來深拷貝後的值
// obj1[key] = extend(value)
if(typeof value ==="object" && value !== null){
obj1[key] = extend(value)
}else{
obj1[key] = value
}
}
return obj1
}
let obj2 = extend(obj) // 深拷貝測試
obj2.b.push("最後")
console.log(obj2)
console.log(obj) // 深拷貝 不影響拓本 淺拷貝 拓本一起變