你會(huì)不會(huì)在開發(fā)項(xiàng)目的過程中遇到這樣的問題废麻,經(jīng)常會(huì)拿到一個(gè)數(shù)據(jù)后需要拷貝一份副本出來,而且很多前端框架都是拷貝的绑嘹,針對(duì)以上的問題小猿圈講師分享給大家JavaScript深拷貝和淺拷貝浸剩,希望對(duì)于學(xué)習(xí)中的你,有一定的幫助窒舟。
涉及到了JS中對(duì)數(shù)據(jù)的深淺拷貝問題,所謂深淺拷貝诵盼,淺拷貝的意思就是惠豺,你只是復(fù)制了對(duì)象數(shù)據(jù)的引用,并沒有把內(nèi)存里的值另外復(fù)制一份风宁,那么深拷貝就是把值完整地復(fù)制一份新的值洁墙。操作拷貝之后的數(shù)據(jù)不會(huì)影響到原數(shù)據(jù)的值拷貝,就是深拷貝戒财,反正热监,有影響則為淺拷貝。
一固翰、應(yīng)用場景
日常開發(fā)中狼纬,JS拷貝大多會(huì)在數(shù)據(jù)保存,數(shù)據(jù)比對(duì)骂际,數(shù)據(jù)同步時(shí)出現(xiàn),所以冈欢,當(dāng)你在這些場景的時(shí)候歉铝,要記得里面隱藏有一個(gè)數(shù)據(jù)深淺拷貝的問題。
二凑耻、淺拷貝
functionclone(origin){
varresult={};
for(varpropinorigin){
if(origin.hasOwnProperty(prop)){
result[prop]=origin[prop];
}
}
returnresult;
}
varjay={
name:"jayChou",
age:40,
family:{
wife:"Quinlivan"
}
}
varotherJay=clone(jay);
otherJay.age=18;
otherJay.family.wife="otherGirl";
console.log(jay);
//
//{
//name:"jayChou",
//age:40,//沒被改變
//family:{
//wife:"otherGirl"http://同時(shí)被改變太示,說明是同一個(gè)引用
//}
//}
console.log(otherJay);
//
//{
//name:"jayChou",
//age:18,
//family:{
//wife:"otherGirl"http://被改變了
//}
//}
我們發(fā)現(xiàn),首先香浩,淺拷貝不是直接賦值类缤,淺拷貝新建了一個(gè)對(duì)象,然后將源對(duì)象的屬性都一一復(fù)制過來,復(fù)制的是值邻吭,而不是引用餐弱。
我們知道,對(duì)象都是按地址引用進(jìn)行訪問的囱晴,淺拷貝的復(fù)制只復(fù)制了第一層的屬性膏蚓,并沒有遞歸將所有的值復(fù)制過來,所以畸写,操作拷貝數(shù)據(jù)驮瞧,對(duì)原數(shù)據(jù)產(chǎn)生了影響,故而為淺拷貝枯芬。進(jìn)而论笔,那些可以直接返回原數(shù)組的方法就可以簡單實(shí)現(xiàn)數(shù)組和對(duì)象淺拷貝采郎。
//1、數(shù)組淺拷貝-slice
functionshallowCopy1(origin){
returnorigin.slice();
}
//2狂魔、數(shù)組淺拷貝-concat
functionshallowCopy2(origin){
returnorigin.concat();
}
//3蒜埋、數(shù)組淺拷貝-遍歷
functionshallowCopy3(origin){
varresult=[];
for(vari=0;i<origin.length;i++){
result.push(origin[i]);
}
returnresult;
}
//4、對(duì)象淺拷貝-Object.assign
functionshallowCopy4(origin){
returnObject.assign({},origin)
}
//5毅臊、對(duì)象淺拷貝-擴(kuò)展運(yùn)算符
//擴(kuò)展運(yùn)算符(...)用于取出參數(shù)對(duì)象的所有可遍歷屬性理茎,拷貝到當(dāng)前對(duì)象之中
functionshallowCopy5(origin){
return{
...origin
}
}
Object.assign的拷貝,假如源對(duì)象的屬性值是一個(gè)指向?qū)ο蟮囊霉苕遥仓豢截惸莻€(gè)引用值皂林。MDN有相應(yīng)的實(shí)例和解釋。
三蚯撩、深拷貝
深拷貝就完整復(fù)制數(shù)據(jù)的值(而非引用)础倍,目的在于避免拷貝后數(shù)據(jù)對(duì)原數(shù)據(jù)產(chǎn)生影響。
//1.深拷貝-JSON正反序列化
//缺點(diǎn)就是無法拷貝undefined胎挎、function沟启、symbol這類特殊的屬性值。
functiondeepClone1(origin){
returnJSON.parse(JSON.stringify(arr));
}
//2.深拷貝-遞歸;
functiondeepClone2(origin){
constresult=origin.constructor===Array?[]:{};
for(letkeysinorigin){
//不遍歷原型鏈上的屬性
if(origin.hasOwnProperty(keys)){
if(origin[keys]&&typeoforigin[keys]==="object"){
//如果值是對(duì)象犹菇,就遞歸一下,區(qū)分是一般對(duì)象還是數(shù)組對(duì)象
result[keys]=origin[keys].constructor===Array?[]:{};
//如果是引用數(shù)據(jù)類型德迹,會(huì)遞歸調(diào)用
result[keys]=deepClone(origin[keys]);
}else{
//如果不是,就直接賦值
result[keys]=origin[keys];
}
}
}
returnresult;
}
JS的深拷貝的應(yīng)用揭芍,需要根據(jù)你的使用場景進(jìn)行使用胳搞,首先是有無必要深拷貝,其次是數(shù)據(jù)類型称杨,是否直接使用JSON的API其實(shí)就可以肌毅。
經(jīng)過小猿圈老師的介紹相信很多同學(xué)對(duì)于JavaScript深拷貝和淺拷貝有了一定的了解,不過大家不要忘記點(diǎn)贊姑原、收藏悬而、轉(zhuǎn)發(fā)呦,讓更多和你一樣有同樣問題的同學(xué)得到幫助锭汛,小猿圈為大家提供一個(gè)良好的學(xué)習(xí)平臺(tái)笨奠。