物件深拷貝

2021-09-20 03:46:43 字數 2824 閱讀 2045

最近在專案中用到了物件拷貝這一塊,而且用到的是物件的深拷貝。下面就讓我們來看一下關於物件的拷貝–淺拷貝和深拷貝。

先看一下深拷貝和淺拷貝的區別(概念)

js 中的淺拷貝與深拷貝,只是針對複雜資料型別(object,array)的複製問題。淺拷貝與深拷貝都可以實現在已有物件上再生出乙份的作用。但是物件的例項是儲存在堆記憶體中然後通過乙個引用值去操作物件,由此拷貝的時候就存在兩種情況了:拷貝引用和拷貝例項,這也是淺拷貝和深拷貝的區別。

淺拷貝:淺拷貝是拷貝引用,拷貝後的引用都是指向同乙個物件的例項,彼此之間的操作會互相影響;

深拷貝:在堆中重新分配記憶體,並且把源物件所有屬性都進行新建拷貝,以保證深拷貝的物件的引用圖不包含任何原有物件或物件圖上的任何物件,拷貝後的物件與原來的物件是完全隔離,互不影響;

我原先用的是es6中的object.assign()方法,發現它只能做一些簡單的屬性拷貝。用**說話:

let obj1 = ;

let obj2 = {};

object.assign(obj2,obj1)

// obj2

obj2.a = 9;

obj1.a // 1

從上可以看出基本資料型別的屬性的拷貝是沒有問題的

那麼我們來看一下如果含有物件或陣列這樣的屬性時呢?

let obj3 = };

let obj4 = {};

object.assign(obj4,obj3)

}obj4.d.d1 = 9;

obj3.d.d1 // 9

可以看出這個時候修改obj4中d物件屬性中的值得時候,obj3中也會跟著改變,這說明object.assign()在拷貝物件或陣列這樣的屬性時是屬於淺拷貝的。

那麼當我們需要用到深拷貝物件的時候,怎麼辦呢?有這樣幾種方法

1.常見的json.stringfy()和json.parse()上面的obj3和obj4用這個方法試一下看效果如何

let obj3 = };

let temp = json.stringify(obj3);

let obj4 = json.parse(temp);

obj4 // };

obj4.d.d1 = 10;

obj3.d.d1; // 9

可以看到經過json.stringfy()和json.parse()的轉化就可以進行深拷貝了

但是這個是有缺陷的,請看**

let obj3 = ,e()}

let temp = json.stringify(obj3);

let obj4 = json.parse(temp);

obj4 // }

結果可以看到obj4中丟失了e()這個函式型別 ,由此可知物件中含有function型別的方法時,使用json.stringfy()和json.parse()是沒有辦法拷貝的,同時也包括正則物件,symbol型別,看下面的例子

let sym = symbol('sym');

let obj12=

let temp2 = json.stringify(obj12);

let obj13 = json.parse(temp2)

obj13 // }

可以看到當物件中含有正規表示式的屬性時,使用json.stringfy()和json.parse()是進行深拷貝時,結果得到的是乙個空物件。

所以通過json.stringify實現深拷貝有幾點要注意

1.拷貝的物件的值中如果有函式,undefined,symbol則經過json.stringify()序列化後的json字串中這個鍵值對會消失

2.無法拷貝不可列舉的屬性,無法拷貝物件的原型鏈

3.拷貝date引用型別會變成字串

4.拷貝regexp引用型別會變成空物件

5.物件中含有nan、infinity和-infinity,則序列化的結果會變成null

6.無法拷貝物件的迴圈應用(即obj[key] = obj)

那麼有沒有更好的方法可以解決上述的問題呢?有,有這樣幾種方法可以解決上述問題以實現物件的深拷貝。且容我慢慢總結實踐一下。

2.迭代遞迴法

這個也是比較常用的方法,可以和方法1進行對比記憶

function deepclone(obj)  // 判斷要轉殖的資料是物件還是陣列

for(let key in obj) ;

cloneobj[key] = deepclone(obj[key]) // 遞迴呼叫 (自己內部呼叫自己)

}else}}

return cloneobj;

}// 實際應用一下

let originobj = },g:[1,2,3,4,5],h()}

originobj

// }, g: array(5), h: ƒ}

let targinobj = deepclone(originobj)

targinobj

// }, g: array(5), h: ƒ}

targinobj.b.e.f = 9

// 9

originobj.b.e.f

// 2

可以看到使用上面的方法當巢狀多層的時候和包含函式屬性的時候都可以進行深拷貝的。

這個方法在實際開發中是可行的,只不過如果包含symbol型別,正規表示式等特殊的型別時,還需要對這個方法進行擴充套件。深拷貝更深級版將在方法3中揭曉,敬請期待。

js 物件深拷貝 深拷貝與淺拷貝

前言 最近在複習一些面試的知識點,剛剛好複習到了這一部分,於是就寫下這篇文章記錄一下。一 值型別和引用型別 在學習深拷貝和淺拷貝之前,我們先來了解一下js的變數型別。值型別 vs 引用型別 值型別 值型別主要有 number,string,boolean,symbol,null,undefined ...

物件陣列的深拷貝和物件的深拷貝

1 對於 普通陣列 陣列元素為數字或者字串 深拷貝很簡單,拷貝之後兩個陣列指標指向的儲存位址不同,從而完成深拷貝 var test 1,2,3 原陣列 var testcopy concat test 拷貝陣列 testcopy 0 4 console.log test 1,2,3 console....

vue物件深拷貝 vue 深拷貝學習

關於vue中json.parse json.stringify 使用深拷貝問題 一般我們單獨用json.parse 或json.stringify 今天在學vue看到json.parse json.stringify 的用法,這裡研究一下 首先分別說下他們的用法 json.parse 是將字串中的物...