1. 程式人生 > >陣列和物件的深拷貝

陣列和物件的深拷貝

在實際開發中,如果遇到稍微複雜一點的邏輯,經常會遇到要複製物件或陣列的場景。而在複製之後,我們會發現改了副本,原物件或陣列的資料也相應改變了。這就是深拷貝的問題。

其原理涉及到記憶體,簡單來說,我們的淺拷貝就是新建一個變數,指向目標變數,而不佔用新的記憶體,所有一旦改變,就是直接改變的記憶體中的值,所以原來的值也改變了。

深拷貝就是,啟用新的記憶體,所以修改新的值,將不影響舊的值。

 

會產生新記憶體的一些常用公共方法:

concat,slice

比如,var new_arr = arr.concat();var new_arr = arr.slice()

 

原本以為這樣就可以一勞永逸,直到遇到一個無限巢狀迴圈的陣列的場景。

結構如上。我們使用上邊兩個方法進行深拷貝之後,發現,改動一級不會影響原資料,但是改動了內部二級資料之後,原資料就變了。

 

解決辦法:

1.物件-字元-物件轉化,適用於物件和陣列,不適用於方法

var new_arr = JSON.parse(JSON.stringify(arr))

 

2.遞迴深拷貝

程式碼 :

 1 var deepCopy = function(obj) {
 2   // 只拷貝物件
 3   if (typeof obj !== 'object') return
; 4 // 根據obj的型別判斷是新建一個數組還是一個物件 5 var newObj = obj instanceof Array ? [] : {}; 6 for (var key in obj) { 7 // 遍歷obj,並且判斷是obj的屬性才拷貝 8 if (obj.hasOwnProperty(key)) { 9 // 判斷屬性值的型別,如果是物件遞迴呼叫深拷貝 10 newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
11 } 12 } 13 return newObj; 14 }

附封裝的淺拷貝方法:

 1 var shallowCopy = function (obj) {
 2   // 只拷貝物件
 3   if (typeof obj !== 'object') return;
 4   // 根據obj的型別判斷是新建一個數組還是一個物件
 5   var newObj = obj instanceof Array ? [] : {};
 6   // 遍歷obj,並且判斷是obj的屬性才拷貝
 7   for (var key in obj) {
 8     if (obj.hasOwnProperty(key)) {
 9       newObj[key] = obj[key];
10     }
11   }
12   return newObj;
13 }