深拷貝與淺拷貝區(qū)別,以及深拷貝常用用法

前言

今天在使用Object.assign()方法時(shí)候,雖然知道此方法是淺拷貝,但是在以下代碼遇到點(diǎn)不理解,于是順便理了一下深拷貝與淺拷貝。

let target = { a:1, b: 2 };
let source = { b: 3, c: 4 };
const returnedTarget = Object.assign({},target, source);
returnedTarget.a=5
console.log(target);//{ a: 1, b: 2 }
console.log(returnedTarget);//{ a: 5, b: 3, c: 4 }

傻乎乎以為是淺拷貝,以為target的a也會(huì)改為5,結(jié)果打臉了。

淺拷貝與深拷貝

簡(jiǎn)單點(diǎn)來說,就是假設(shè)B復(fù)制了A,當(dāng)修改A時(shí),看B是否會(huì)發(fā)生變化,如果B也跟著變了,說明這是淺拷貝,拿人手短,如果B沒變,那就是深拷貝,自食其力。

let a=[1,2,3]
let b=a;
b[0]=0;
console.log(a);//[0, 2, 3]
console.log(b);//[0, 2, 3]

=賦值就是典型的淺拷貝,當(dāng)改變b的值時(shí)候,a的值會(huì)跟著改變。
這里就牽扯到基本數(shù)據(jù)類型與復(fù)雜數(shù)據(jù)類型。

基本數(shù)據(jù)類型與復(fù)雜(引用)數(shù)據(jù)類型

基本數(shù)據(jù)類型:number,null,undefined,string,boolean,symbol
復(fù)雜數(shù)據(jù)類型:對(duì)象({a:1}),數(shù)組:([1,2,3]),函數(shù)等。
基本類型-名值存儲(chǔ)在棧內(nèi)存中,例如let a=1;


image.png

當(dāng)b=a時(shí),棧內(nèi)存會(huì)重新開辟一塊內(nèi)存,


image.png

當(dāng)修改b時(shí)候,a不會(huì)改變,這是因?yàn)閍與b存儲(chǔ)在不同的內(nèi)存中,但這不算是深拷貝,因?yàn)樯羁截惐旧碇会槍?duì)較為復(fù)雜的object類型數(shù)據(jù)。
引用類型--名存在棧內(nèi)存中,值存在于堆內(nèi)存中,但是棧內(nèi)存會(huì)提供一個(gè)引用的地址指向堆內(nèi)存中的值


image.png

當(dāng)b=a進(jìn)行拷貝時(shí),其實(shí)復(fù)制的是a的引用地址,而并非堆里面的值。


image.png

而當(dāng)我們a[0]=1時(shí)進(jìn)行數(shù)組修改時(shí),由于a與b指向的是同一個(gè)地址,所以自然b也受了影響,這就是所謂的淺拷貝了。
image.png

那,要是在堆內(nèi)存中也開辟一個(gè)新的內(nèi)存專門為b存放值,就像基本類型那樣,豈不就達(dá)到深拷貝的效果了


image.png

深拷貝方法

1.自己封裝一個(gè)深拷貝方法

function deepClone(obj){
    let objClone=Array.isArray(obj)?[]:{};
    if(obj&&typeof obj==='object'){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                    if(obj[key]&&typeof obj[key]==='object'){
                        objClone[key]=deepClone(obj[key])
                    }else{
                      objClone[key]=obj[key]
                    }
            }
        }
    }
    return objClone;
}
let a=[1,2,3];
let b=deepClone(a);
b[0]=4;
console.log(b,a)
//Array [4, 2, 3] Array [1, 2, 3]

此方法原理為拷貝對(duì)象各個(gè)層級(jí)的屬性,每一層都擁有獨(dú)立的棧內(nèi)存。
2.使用JSON對(duì)象的parse和stringify

function deepClone(obj){
    let objString=JSON.stringify(obj);
    let objClone=JSON.parse(objString);
    return objClone;
}
let a=[1,2,3];
let b=deepClone(a);
b[0]=4;
console.log(b,a);
//Array [4, 2, 3] Array [1, 2, 3]

總結(jié)

寫到這里也基本了解了深拷貝與淺拷貝,也知道為什么要使用深拷貝,以及怎么實(shí)現(xiàn)深拷貝,關(guān)于JS內(nèi)存空間的文章,若有興趣歡迎閱讀 JS 從內(nèi)存空間談到垃圾回收機(jī)制 這篇文章。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容