之所有寫這篇文章,是因?yàn)榍皫滋煸陧?xiàng)目中被ES6的assign坑了襟企,后來自己查閱了些資料,覺得有必要總結(jié)下寝凌。
淺拷貝
平常我們把字符串柒傻,數(shù)字的值賦值給新變量,相當(dāng)于把值完全復(fù)制過去较木,新變量的值改變不會(huì)影響舊變量红符,
let num = 123
let num2 = num
num2 = 321
console.log(num) //123
console.log(num2) //321
但是對象卻不同
let obj = { name: '程序猿' }
let obj2 = obj
obj2.name = '單身狗'
console.log(obj) //{ name: '單身狗' }
因?yàn)槎际且玫耐粋€(gè)地址,所以你變他也變(0.0 真是調(diào)皮)
ES6出來后伐债,新增了Object.assign 用來復(fù)制對象预侯,嗯~~~來試試
let obj = { name: '程序猿', age:{child: 12} }
let copy = Object.assign({}, obj);
copy.name = '單身狗'
copy.age.child = 24
console.log(obj) // { name: '程序猿', age:{child: 24} }
嗯~~~不錯(cuò),程序猿還沒變成單身狗峰锁,納尼child怎么變成24了萎馅,我怕是用了假的ES6吧
查了查MDN,才發(fā)現(xiàn)自己對Object.assign的一點(diǎn)都不了解虹蒋,就亂用糜芳,真是自己作死
簡單說就是如果拷貝的對象的屬性值也是一個(gè)引用(對象)飒货,就只會(huì)把引用給拷貝過來。而且這貨用的最多的地方不是淺拷貝而是將多個(gè)對象的屬性合并到一個(gè)對象上
Object.assign( target, obj1, obj2 )
第一個(gè)參數(shù)是目標(biāo)對象峭竣,后面的都是源對象塘辅,將源對象的屬性復(fù)制到目標(biāo)對象中
深拷貝
既然沒有現(xiàn)成的深拷貝的方法,那有哪些方式可以達(dá)到深拷貝呢皆撩?
對象的賦值會(huì)相互影響扣墩,而數(shù)字,字符串之類的不會(huì)扛吞,我們將對象逐漸遍歷呻惕,在數(shù)字,字符串將其對應(yīng)賦值喻粹,這就是一般深拷貝的方式
function cloneDeep(obj){
if( typeof obj !== 'object' || Object.keys(obj).length === 0 ){
return obj
}
let resultData = {}
return recursion(obj, resultData)
}
function recursion(obj, data={}){
for(key in obj){
if( typeof obj[key] == 'object' && Object.keys(obj[key].length>0 )){
data[key] = recursion(obj[key])
}else{
data[key] = obj[key]
}
}
return data
}
let obj = {name:'程序猿',age:{child:20}}
let obj2 = cloneDeep(obj)
obj.name = '單身狗'
obj2.age.child = 24
console.log(obj) // {name:'程序猿',age:{child:20}}
一長串的看起來好麻煩啊蟆融,我只是想深拷貝個(gè)對象啊
這里有一種取巧的方式就是使用json轉(zhuǎn)換,
let h = JSON.parse(JSON.stringify(a));
這里是將對象轉(zhuǎn)化為json字符串又轉(zhuǎn)換為json對象守呜,之前什么引用的全變了樣兒型酥,不過弊端也是有的,繼承的屬性會(huì)丟失
這里推薦使用Lodash類庫
參考資料