es6出的這個Object.assign()在大部分的場景當中都會使用,比方說寫redux中reducer的純函數(shù)、或者在提交之前處理提交的數(shù)據(jù)之類的。
但它有一個問題,它是淺拷貝,因為Object.assign()拷貝的是對象的屬性值,如果屬性值是一個對象的引用,那么它拷貝的就是那個對象的引用值。
let obj = {
a: 1,
b: 2,
c: {
a: 111
}
}
let newObj = Object.assign({}, obj)
console.log(obj) //{ a: 1, b: 2, c: { a: 111 } }
console.log(newObj) //{ a: 1, b: 2, c: { a: 111 } }
obj.a = 222
console.log(obj) //{ a: 222, b: 2, c: { a: 111 } }
console.log(newObj) //{ a: 1, b: 2, c: { a: 111 } }
obj.c.a = 1
console.log(obj) //{ a: 222, b: 2, c: { a: 1 } }
console.log(newObj) //{ a: 1, b: 2, c: { a: 1 } }
很明顯能看出來,屬性為一個對象的索引,就會導致拷貝的值一起變化,因為他們的地址是一樣的。
那么只能自己來寫一個,既然說到了es6,那就用es6寫一個:
const deepClone = obj => {
if (!obj || typeof obj !== 'object') {
return obj
}
let o = {}
if (Array.isArray(obj)) {
o = obj.map(item => deepClone(item))
} else {
Object.keys(obj).forEach((key) => {
return o[key] = deepClone(obj[key])
})
}
return o
}
這種比JSON.parse(JSON.stringify())要更加通用。
支持null、undefined、NaN、Infinity