????????在js中锡足,數(shù)據(jù)類型類型可分為值類型(基本類型)和引用類型。值類型有:字符串(String)壳坪、布爾(Boolean)舶得、數(shù)字(Number)、對空(Null)爽蝴、未定義(undefined)沐批、Symbol纫骑。引用類型:對象(Object)、數(shù)組(Array)九孩、函數(shù)(Function)先馆。這兩種類型的不同,使得在拷貝的時候也會有差異躺彬。值類型拷貝的時候直接賦值就好煤墙,但是在引用類型的對象和數(shù)組中,如果直接整體賦值的話有的時候是會有問題的顾患。在項目中番捂,我們經(jīng)常需要保存一份原始數(shù)據(jù),然后拷貝一份原始數(shù)據(jù)進行更改江解,那么如果這個數(shù)據(jù)是Object或者Array類型设预,我們直接拷貝的話,他們還是指向的同一個地址犁河,所以鳖枕,當我們改變其中的一個值或者新增一個屬性時,另一份也會跟著變化桨螺,這肯定不是我們想要的結(jié)果宾符,那么今天就總結(jié)一下js中,對象灭翔、數(shù)組拷貝的問題魏烫。
????????拷貝的問題也是分為兩種,一種是淺拷貝肝箱、另一種是深拷貝哄褒。在總結(jié)之前,我們先定義一個較復(fù)雜的對象名為Obj,后面的代碼都是使用該對象進行更改的煌张,具體結(jié)構(gòu)如下:
let Obj = {
????name:'zhang',
????age:18,
????score:{
????????Chinese:98,
????????English:88,
????????Math:98
????},
????like:[{
????????????sports:5
? ? ? ? ? },
????????{
????????????sports:4
????????},{
????????????sports:3
????????}]
}
一呐赡、淺拷貝
1、淺拷貝之使用Object.assign方式
function ObjCopy1(){
????let Obj1 = Object.assign({},Obj,);
????Obj1.name = 'zhang1';
????Obj1.like[1].sports = 55;
????Obj1.score.Chinese = 100,
????console.log('Obj.name:',Obj.name,' Obj.like[1].sports:',Obj.like[1].sports,'? ????Obj.score.Chinese:',Obj.score.Chinese);
????console.log('Obj1.name:',Obj1.name,'? Obj1.like[1].sports',Obj1.like[1].sports,'? ????Obj1.score.Chinese:',Obj1.score.Chinese);
}
ObjCopy1();
2骏融、淺拷貝之...運算符實現(xiàn)
function ObjCopy2(){
????let Obj2 = {...Obj};
????Obj2.name = 'zhang1';
????Obj2.like[1].sports = 55;
????Obj2.score.Chinese = 100,
????console.log('Obj.name:',Obj.name,'? Obj.like[1].sports:',Obj.like[1].sports,'? ????Obj.score.Chinese:',Obj.score.Chinese);
????console.log('Obj2.name:',Obj2.name,'? Obj2.like[1].sports',Obj2.like[1].sports,'? ????Obj2.score.Chinese:',Obj2.score.Chinese);
}
ObjCopy2();
3链嘀、淺拷貝之一重循環(huán)直接遍歷
function ObjCopy3(Obj){
????let Obj3={};
????for (let item in Obj){
????????Obj3[item] = Obj[item]
????}
????Obj3.name = 'zhang1';
????Obj3.like[1].sports = 55;
? ? Obj3.score.Chinese = 100,
????console.log('Obj.name:',Obj.name,'? Obj.like[1].sports:',Obj.like[1].sports,'? ????Obj.score.Chinese:',Obj.score.Chinese);
????console.log('Obj3.name:',Obj3.name,'? Obj3.like[1].sports',Obj3.like[1].sports,'? ????Obj3.score.Chinese:',Obj3.score.Chinese);
}
????????通過結(jié)果可以看到,通過以上三種方式實現(xiàn)的拷貝都是淺拷貝档玻,當嵌套多層Object或Array時怀泊,我們更改value中的對象或Array的值時,原始數(shù)據(jù)也跟著變化了窃肠。
二包个、深拷貝
1、深度拷貝之使用JSON.parse()和JSON.stringify()
function ObjCopy4(){
????let Obj4 = JSON.parse(JSON.stringify(Obj));
????Obj4.name = 'zhang1';
????Obj4.like[1].sports = 55;
????Obj4.score.Chinese = 100,
????console.log('Obj.name:',Obj.name,'? Obj.like[1].sports:',Obj.like[1].sports,'? ????Obj.score.Chinese:',Obj.score.Chinese);
????console.log('Obj4.name:',Obj4.name,'? Obj4.like[1].sports',Obj4.like[1].sports,'? ????Obj4.score.Chinese:',Obj4.score.Chinese);
}
ObjCopy4();
2碧囊、利用遞歸树灶,自定義深度拷貝
function ObjCopy5(){
function copy (Obj) {
? ? ? ? var newObj = Obj.constructor === Array ? [] : {};
? ? ? ? if(typeof Obj !== 'object'){
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? for(var i in Obj){
? ? ? ? ? newObj[i] = typeof Obj[i] === 'object' ?
? ? ? ? ? copy(Obj[i]) : Obj[i];
? ? ? ? }
? ? ? ? return newObj
}
var Obj5 = copy(Obj)
Obj5.name = 'zhang1';
Obj5.like[1].sports = 55;
Obj5.score.Chinese = 100,
console.log('Obj.name:',Obj.name,'? Obj.like[1].sports:',Obj.like[1].sports,'? Obj.score.Chinese:',Obj.score.Chinese);
console.log('Obj5.name:',Obj5.name,'? Obj5.like[1].sports',Obj5.like[1].sports,'? Obj5.score.Chinese:',Obj5.score.Chinese);
}
????????這兩種方法都能實現(xiàn)深度拷貝,此處只是針對Object和Array糯而,F(xiàn)unction的不一定能夠拷貝成功天通。一般情況下針對只含有Object和Array的對象拷貝時,使用JSON.parse()和JSON.stringify()方法拷貝是非常簡單的熄驼。此處我只總結(jié)了5種方法像寒,如果有其它的方法,也希望大家能夠多分享哦瓜贾。