深淺拷貝
let a = {
age: 1
}
let b = a
a.age = 2
console.log(b.age) // 2
從上面的例子可以發(fā)現(xiàn),如果給一個變量賦值一個對象,那么兩者的值會是同一個引用,其中一方改變,另一方也會相應改變。
解決這個問題,可以引入淺拷貝:
淺拷貝
- 可以使用
Object.assign來解決這個問題
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
- 使用ES6展開運算符(...)解決
let a = {
age: 1
}
let b = {...a}
a.age = 2
console.log(b.age) // 1
通常淺拷貝能解決大部分的問題,但是當遇到,對象里面嵌套一個對象的時候,就需要用到深拷貝了
let a = {
age: 1,
name: {
first: 'black'
}
}
let = {...a}
a.name.first = 'guyue'
console.log(b.name.first) // guyue
這樣說明淺拷貝并沒有對嵌套的對象生效。此時需要深拷貝上場:
深拷貝
深拷貝最簡單的實現(xiàn)辦法就是使用JSON.parse(JSON.stringify(object)) 來解決。
let a = {
age: 1,
name: {
first: 'black'
}
}
let b = JSON.parse(JSON.stringify(a))
a.name.first = 'guyue'
console.log(b.name.first) // black
但是當出現(xiàn)以下幾種情況的時候,會出現(xiàn)問題:
let obj = {
a: 1,
b: {
c: 2
}
}
obj.c = obj.b
obj.d = obj.a
obj.b.c = obj.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)
// Uncaught TypeError: Converting circular structure to JSON
報錯了,不能解決循環(huán)引用對象的問題。
let obj = {
age: undefined,
sex: function(){},
name: 'black'
}
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj) // {name: "black"}
發(fā)現(xiàn)只拷貝了name,而忽略了undefined和funcion。
所以,JSON.parse(JSON.stringify(obj))遇到這幾種情況會出現(xiàn)問題:
- 不會拷貝
undefined - 不能拷貝函數(shù)
- 不能解決循環(huán)引用的對象
所以采用下面的方式:
function deepClone(obj) {
let res = obj instanceof Array ? [] : {}
for(let k in obj) {
res[k] = obj[k]
if(typeof obj[k] === Object) {
deepClone(obj[k])
}
}
return res
}
let obj = {
age: undefined,
sex: function(){},
name: 'black'
}
let newObj = deepClone(obj)
console.log(newObj) // {age: undefined, sex: ?, name: "black"}
可以采用ES2017的新語法:
function copyObject(orig) {
return Object.create(
Object.getPrototypeOf(orig),
Object.getOwnPropertyDescriptors(orig)
);
}
let obj = {
age: undefined,
sex: function(){},
name: 'black'
}
let newObj = copyObject(obj)
console.log(newObj) // {age: undefined, sex: ?, name: "black"}