JS的深淺拷貝

引用類型

之所以會(huì)出現(xiàn)深淺拷貝的問(wèn)題,實(shí)質(zhì)上是由于JS對(duì)基本類型和引用類型的處理不同?;绢愋椭傅氖呛?jiǎn)單的數(shù)據(jù)段,而引用類型指的是一個(gè)對(duì)象,而JS不允許我們直接操作內(nèi)存中的地址,也就是不能操作對(duì)象的內(nèi)存空間,所以,我們對(duì)對(duì)象的操作都只是在操作它的引用而已。

在復(fù)制時(shí)也是一樣,如果我們復(fù)制一個(gè)基本類型的值時(shí),會(huì)創(chuàng)建一個(gè)新值,并把它保存在新的變量的位置上。而如果我們復(fù)制一個(gè)引用類型時(shí),同樣會(huì)把變量中的值復(fù)制一份放到新的變量空間里,但此時(shí)復(fù)制的東西并不是對(duì)象本身,而是指向該對(duì)象的指針。所以我們復(fù)制引用類型后,兩個(gè)變量其實(shí)指向同一個(gè)對(duì)象,改變其中一個(gè)對(duì)象,會(huì)影響到另外一個(gè)。

var num = 10;
var obj = {
    name: 'Nicholas'
}

var num2 = num;
var obj2 = obj;

obj.name = 'Lee';
obj2.name; // 'Lee'

淺拷貝

1.Object.assign()

其中第一個(gè)參數(shù)是我們最終復(fù)制的目標(biāo)對(duì)象,后面的所有參數(shù)是我們的即將復(fù)制的源對(duì)象,支持對(duì)象或數(shù)組,一般調(diào)用的方式為

var newObj = Object.assign({}, originObj);

這樣我們就得到了一個(gè)新的淺拷貝對(duì)象。另外[].slice()方法可以視為數(shù)組對(duì)象的淺拷貝。

2. 自定義淺拷貝

如果我們要復(fù)制對(duì)象的所有屬性都不是引用類型時(shí),就可以使用淺拷貝,實(shí)現(xiàn)方式就是遍歷并復(fù)制,最后返回新的對(duì)象。

function shallowCopy(obj) {
    var copy = {};
    // 只復(fù)制可遍歷的屬性
    for (key in obj) {
        // 只復(fù)制本身?yè)碛械膶傩?        if (obj.hasOwnProperty(key)) {
            copy[key] = obj[key];
        }
    }
    return copy;
}

如上面所說(shuō),我們使用淺拷貝會(huì)復(fù)制所有引用對(duì)象的指針,而不是具體的值,所以使用時(shí)一定要明確自己的需求,同時(shí),淺拷貝的實(shí)現(xiàn)也是最簡(jiǎn)單的。

深拷貝

如果我們需要復(fù)制一個(gè)擁有所有屬性和方法的新對(duì)象,就要用到深拷貝,JS并沒(méi)有內(nèi)置深拷貝方法,主要是因?yàn)椋?/p>

  1. 深拷貝怎么定義?我們?cè)趺刺幚碓??怎么區(qū)分可拷貝的對(duì)象?原生DOM/BOM對(duì)象怎么拷貝?函數(shù)是新建還是引用?這些edge case太多導(dǎo)致我們無(wú)法統(tǒng)一概念,造出大家都滿意的深拷貝方法來(lái)。
  2. 內(nèi)部循環(huán)引用怎么處理,是不是保存每個(gè)遍歷過(guò)的對(duì)象列表,每次進(jìn)行對(duì)比,然后再造一個(gè)循環(huán)引用來(lái)?這樣帶來(lái)的性能消耗可以接受嗎。
var obj1 = {
    age: 20,
    name: 'xxx',
    address: {
        city: 'beijing'
    },
    arr: ['a', 'b', 'c']
}
var obj2 = deepClone(obj1)
obj2.address.city = '上海'

console.log(obj2)
console.log(obj1)

function deepClone(obj = {}) {
    if (typeof obj !== 'object' || obj == null) {
        return obj
    }
    let result;
    if (obj instanceof Array) {
        result = []
    } else {
        result = {}
    }
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            result[key] = deepClone(obj[key]);
        }
    }
    return result
}

WX20220222-111413@2x.png
?著作權(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)容

  • JS存儲(chǔ)方式 JS中存在基本數(shù)據(jù)類型和引用數(shù)據(jù)類型1.基本數(shù)據(jù)類型:number,string,boolean,n...
    壹豪閱讀 398評(píng)論 0 0
  • 轉(zhuǎn)載于:https://www.cnblogs.com/136asdxxl/p/8645750.html 一、js...
    小鳳年閱讀 7,761評(píng)論 0 6
  • 原網(wǎng)址:https://www.cnblogs.com/dengyao-blogs/p/11466598.html...
    王果果閱讀 455評(píng)論 0 0
  • 先看JS的數(shù)據(jù)類型 基本類型:Undefined、Null、Boolean、Number 和 String 引用類...
    噠吧將閱讀 359評(píng)論 0 0
  • 淺拷貝 前面已經(jīng)提到,在定義一個(gè)對(duì)象或數(shù)組時(shí),變量存放的往往只是一個(gè)地址。當(dāng)我們使用對(duì)象拷貝時(shí),如果屬性是對(duì)象或數(shù)...
    泉泉泉泉泉泉閱讀 249評(píng)論 0 2

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