陣列和物件的深拷貝
阿新 • • 發佈:2018-11-21
在實際開發中,如果遇到稍微複雜一點的邏輯,經常會遇到要複製物件或陣列的場景。而在複製之後,我們會發現改了副本,原物件或陣列的資料也相應改變了。這就是深拷貝的問題。
其原理涉及到記憶體,簡單來說,我們的淺拷貝就是新建一個變數,指向目標變數,而不佔用新的記憶體,所有一旦改變,就是直接改變的記憶體中的值,所以原來的值也改變了。
深拷貝就是,啟用新的記憶體,所以修改新的值,將不影響舊的值。
會產生新記憶體的一些常用公共方法:
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 }