先來普及一下深拷貝和淺拷貝的區別
淺拷貝:就是簡單的複製,用等號即可完成
let a = {a: 1}
let b = a
這就完成了一個淺拷貝
但是當修改物件b的時候,我們發現物件a的值也被改變了
b.a = 10
console.log(a.a) => 10
這是因為淺拷貝只複製了指向物件的指標,新舊物件共用同一塊記憶體,修改某一個物件的同時也會把另一個都一併修改了
深拷貝:跟淺拷貝最簡單明瞭的區別就是修改拷貝的物件,不會改變源物件
利用Object.assign可以對只有一層的物件實現深拷貝,如下:
let a = {a: 1,b: 2,c: 3}
let b = Object.assign({}, a)
b.b = 100
console.log(a.b) => 2
可以看出來這樣是完全可以做到對只有一層的物件實現深拷貝的
但是如果物件裡面的元素還是物件的話就沒作用了
let a = {a: 1,b: 2,c: 3, d: {a: 1}}
let b = Object.assign({}, a)
b.d.a = 100
console.log(a.d.a) => 100
對於這種比較複雜的物件,我們就可以利用遞迴的方式實現真正的物件深拷貝了
function deepClone (sourceObj, targetObj) {
let cloneObj = targetObj || {}
if(!sourceObj || typeof sourceObj !== "object" || sourceObj.length === undefined){
return sourceObj
}
if(sourceObj instanceof Array){
cloneObj = sourceObj.concat()
} else {
for(let i in sourceObj){
if (typeof sourceObj[i] === `object`) {
cloneObj[i] = deepClone(sourceObj[i], {})
} else {
cloneObj[i] = sourceObj[i]
}
}
}
return cloneObj
}
簡單的幾行程式碼就可以輕鬆實現物件的深拷貝
簡單的測試程式碼,如下:
let sourceObj = {
a: 1,
b: {
a: 1
},
c: {
a: 1,
b: {
a: 1
}
},
d: function() {
console.log(`hello world`)
},
e: [1, 2, 3]
}
let targetObj = deepClone(sourceObj, {})
targetObj.c.b.a = 9
console.log(sourceObj) => { a: 1, b: { a: 1 }, c: { a: 1, b: { a: 1 } }, d: [Function: d], e: [ 1, 2, 3 ] }
console.log(targetObj) => { a: 1, b: { a: 1 }, c: { a: 1, b: { a: 9 } }, d: [Function: d], e: [ 1, 2, 3 ] }
另外介紹兩個用來做深拷貝的庫
**jquery**
使用方法:
let targetObj = $.extent(true,{},sourceObj)
**lodash函式庫**
使用方法:
npm install lodash
**es5寫法**
let lodash = require(`lodash`)
**es6寫法**
import lodash from `lodash`
let targetOj = lodash.cloneDeep(sourceObj)
各位看官覺得有什麼地方不對的請多多指教。