1. 程式人生 > >結合多個例項深入理解js的深拷貝和淺拷貝,多種方法實現物件的深拷貝

結合多個例項深入理解js的深拷貝和淺拷貝,多種方法實現物件的深拷貝

親們為什麼要研究深拷貝和淺拷貝呢,因為我們專案開發中有許多情況需要拷貝一個數組抑或是物件,但是單純的靠=“賦值”並不會解決所有問題,如果遇到引用型別的物件改變新賦值的物件會造成原始物件也發生同樣改變,而要去除影響就必須用到深拷貝,深拷貝,對於引用物件需要進行深拷貝才會去除影響。如果是值型別直接“=”就好。

1.引用型別  引用型別通常叫做類(class),也就是說,遇到引用值,所處理的就是物件。new 出來的物件都是引用物件

(1)值型別:String, 數值、布林值、null、undefined。 對於值型別一個物件一個儲存位置所以會互不干擾

(2)引用型別:物件、陣列、函式。對於引用型別,a=b賦值後的新物件也指向同一個儲存地址所以b變化a跟隨變化

而要改變這種情況需要改變b的指向,使其指向b儲存位置如下圖

下面是各種例項對比:

第一模組-陣列:

陣列淺拷貝:

a =[1,2,3];b=a;b.push('change');console.log('a:'+a,'b:'+b)
VM529:1 a:1,2,3,change b:1,2,3,change

陣列深拷貝://到每一項都是值型別時可以直接賦值

a =[1,2,3];a.forEach(val => b.push(val));b.push('change');console.log('a:'+a,'b:'+b)
VM529:1 a:1,2,3,change,1,2,3,change,1,2,3,change

第二模組-物件:

1-1物件淺拷貝的程式碼及結果

bb改變後原陣列aa也跟隨變化,根本原因就是像第一張線框圖描述的一樣

1-2物件深拷貝程式碼及結果,使用es6的Object.assign()方法

深拷貝bb不會影響aa

1-3物件深拷貝使用JSON.parse(JSON.stringify(obj)),即物件序列化

1-4物件深拷貝使用es6的Object.keys(obj),Object.values(obj)分別獲得鍵陣列和值陣列,再通過函式根據條件迴圈回撥deal()得到深拷貝值:《推薦使用回撥》,留下個小問題,看官們可以試著這個思路去完成陣列和函式回撥實現深拷貝。

可複製程式碼:

aa = {
    key:'1',
    value:'a',
    children:{
        key: '2',
        value: 'b'
    }
};

function deal(obj) {
    bb = {};
    let keyArr = Object.keys(obj);
    let valueArr = Object.values(obj);
    valueArr.forEach((val,index) => {
        if(Object.prototype.toString.call(val) === "[object  Object]") {
            deal(val)
        }else {
            bb[keyArr[index]] = val
        }
    })
    return bb
}
let BB = {}
BB=deal(aa);
BB['add']='addStr';
console.log('aa:',aa,'========','BB:',BB)

截圖程式碼和結果:

第三模組對於物件來說可複製的深拷貝程式碼和結果事例如下:

例項一

aa = {
    key:'1',
    value:'a',
    children:{
        key: '2',
        value: 'b'
    }
};
bb=aa;bb['add']='addStr';console.log('aa:',aa,'====','bb',bb)
VM1098:9 aa: {key: "1", value: "a", children: {…}, add: "addStr"}add: "addStr"children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object ==== bb {key: "1", value: "a", children: {…}, add: "addStr"}add: "addStr"children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object

 

例項二
aa = {
    key:'1',
    value:'a',
    children:{
        key: '2',
        value: 'b'
    }
};
bb = {}
bb=Object.assign({},aa);bb['add']='addStr';console.log('aa:',aa,'====','bb',bb)
VM1223:10 aa: {key: "1", value: "a", children: {…}}children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object ==== bb {key: "1", value: "a", children: {…}, add: "addStr"}add: "addStr"children: key: "2"value: "b"__proto__: Objectconstructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()key: "1"value: "a"__proto__: Object

例項三
aa = {
    key:'1',
    value:'a',
    children:{
        key: '2',
        value: 'b'
    }
};
bb = {}
bb=JSON.parse(JSON.stringify(aa));bb['add']='addStr';console.log('aa:',aa,'====','bb',bb)
VM1653:10 aa: {key: "1", value: "a", children: {…}}children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object ==== bb 

歡迎轉載,轉載請註明出處。歡迎大家交流學習