深拷貝 淺拷貝
淺拷貝
⾸先可以通過 Object.assign 來解決這個問題,很多⼈認為這個函式是⽤來 深拷⻉的。其實並不是, Object.assign 只會拷⻉所有的屬性值到新的物件中,如果屬性值是物件的話,拷⻉的是地址,所以並不是深拷⻉。
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
另外我們還可以通過展開運算子 ... 來實現淺拷⻉
let a = {
age: 1
}
let b = { ...a }
a.age = 2
console.log(b.age) // 1
通常淺拷⻉就能解決⼤部分問題了,但是當我們遇到如下情況就可能需要使⽤ 到深拷⻉了--
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = { ...a }
a.jobs.first = 'native'
console.log(b.jobs.first) // native
淺拷⻉只解決了第⼀層的問題,如果接下去的值中還有物件的話,那麼就⼜回 到最開始的話題了,兩者享有相同的地址。要解決這個問題,我們就得使⽤深拷⻉了。
深拷貝
這個問題通常可以通過 JSON.parse(JSON.stringify(object)) 來解決。
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE
但是該⽅法也是有侷限性的:
·會忽略 undefined
·會忽略 symbol
·不能序列化函式
·不能解決迴圈引⽤的物件
let obj = { a: 1, b: { c: 2, d: 3, }, } obj.c = obj.b obj.e = obj.a obj.b.c = obj.c obj.b.d = obj.b obj.b.e = obj.b.c let newObj = JSON.parse(JSON.stringify(obj)) console.log(newObj)
簡單來說深拷貝就是當遇到值是物件型別的時候就再執行一遍複製:
function deepCopy (obj) { var result; //引用型別分陣列和物件分別遞迴 if (Object.prototype.toString.call(obj) == '[object Array]') { result = [] for (i = 0; i < obj.length; i++) { result[i] = deepCopy(obj[i]) } } else if (Object.prototype.toString.call(obj) == '[object Object]') { result = {} for (var attr in obj) { result[attr] = deepCopy(obj[attr]) } } //值型別直接返回 else { return obj } return result }