為什麼會用到淺拷貝和深拷貝
首先來看一下如下程式碼
let a = b = 2
a = 3
console.log(a)
console.log(b)
let c = d = [1,2,3]
let e = f = {a:1,b:2,c:3}
c[0] = 2
e.a = 2
console.log(d[0])
console.log(f.a)
你會發現,同一個Array或者Object賦值給兩個不同變數時,變數指向的是同一個記憶體地址,所以就會造成其中一個變數改變屬性值,同時改變了另外一個變數的對應屬性值。
而大多數實際專案中,我們想要的結果是兩個變數(初始值相同)互不影響。所以就要使用到拷貝(分為深淺兩種)
深淺拷貝的區別
淺拷貝只複製一層物件的屬性,而深拷貝則遞迴複製了所有層級。
淺拷貝有效性針對的是單一層級物件 [1,2,3]或者{a:1,b:2}
深拷貝有效性針對的是單層或者多層級物件 [1,2,3]或者{a:1,b:2}或者[1,[1],{a:1}]或者{a:[1],b:{c:2}}
淺拷貝
- 如何實現
// 陣列
let a = [1,2]
let b = a.slice()
// {}
let e = {a:[1],b:{d:1},2}
let f = Object.create(e)
function shallowCopy (obj) {
if (typeof obj === `object` && obj !== null) {
if (Array.isArray(obj)) {
return obj.slice()
} else {
let result = {}
Object.keys(obj).forEach((item,i) = > {
console.log(i)
result[item] = obj[item]
})
return result
}
} else {
return obj
}
}
- 應用場景
對於一層結構的Array和Object想要拷貝一個副本時使用
vue的mixin是淺拷貝的一種複雜型式
深拷貝
- 如何實現
// 利用JSON(它能正確處理的物件是Number, String, Boolean, Array, 扁平物件)
let g = JSON.parse(JSON.stringify(obj))
// 適用於
function deepCopy (obj) {
if (typeof obj === `object` && obj !== null) {
let objKeys = Object.keys(obj)
let result
if (Array.isArray(obj)) {
result = []
} else {
if (obj.constructor === Object) {
result = {}
} else {
return obj
}
}
objKeys.forEach((item) => {
if (typeof obj[item] === `object` && obj[item] !== null) {
switch (obj[item].constructor) {
case Array:
result[item] = deepCopy(obj[item])
break
case Object:
result[item] = deepCopy(obj[item])
break
case Date:
result[item] = new Date(obj[item])
break
case RegExp:
let attributes = ``
attributes += obj[item].global ? `g` : ``
attributes += obj[item].ignoreCase ? `g` : ``
attributes += obj[item].multiline ? `g` : ``
result[item] = new RegExp(obj[item].source, attributes);
break
default:
result[item] = obj[item]
break
}
} else {
result[item] = obj[item]
}
})
return result
} else {
return obj
}
}
- 應用場景
複製深層次的object資料結構 - 對深拷貝的應用想法
在實際工作中是不是用繼承來實現更好?需要大家來討論,提意見