JavaScript的深淺復制
為什么有深復制、淺復制?
JavaScript中有兩種資料型別,基本資料型別如undefined、null、boolean、number、string,另一類是Object,簡單資料型別只存盤在記憶體中的堆疊區,復制的時候是值傳遞給新的索引,而復雜資料型別由堆疊區和堆區共同儲存,堆疊區執行同樣的操作,只是把堆地址復制了一份,而真實資料在堆區中依然只有一份,
為了不影響原有資料,那么我們就新建一個物件,遍歷原有物件的屬性賦值到新屬性,
let newObj = {}
for (let prop in obj) {
newObj[prop] = obj[prop]
}
上面這個回圈也可以用Object.assign({}, obj);來實作,
這樣做是否解決問題?未必,因為Object中可以嵌套Object,如果原有物件屬性中有復雜資料型別,那么新的物件中也只能得到一個地址,這種情況被稱為淺復制,我們希望能將物件中的物件,無論多少層,都能復制一份,能達到這種效果的,稱為深復制,
深復制的幾種方法
首先假設有資料
let obj = {
a: 23,
b: [0, 1, [2, 3], function() {console.log('in array')}, undefined],
c: {k: 'value'},
d: function() {console.log('a')}
}
JSON.parse(JSON.stringify(obj))
let newObj = JSON.parse(JSON.stringify(obj))
newObj.newKey = 'newValue'
console.log(obj)
console.log(newObj)
如果處理物件只是簡單的鍵值對,這個方法效果不錯,
這個方法的缺點
- 無法復制函式
- 忽略
undefined值 - 無法處理Set、Map、Symbol型別(即使用上
repalce引數) - 原有的原型鏈會消失
- 回圈參考的物件會報錯
遞回法
因為要處理屬性的值也是Object這種情況,自然可以想到遞回這種處理方法,
function deepCopy(oldObj, newObj) {
let obj = newObj || {}
for (let i in oldObj) {
if (oldObj[i] === obj) { // 防止回圈參考
continue
}
if (typeof oldObj[i] === 'object') {
// obj[i] = (oldObj[i].constructor === Array) ? [] : {}
obj[i] = oldObj[i] instanceof Array ? [] : {}
deepCopy(oldObj[i], obj[i])
} else {
obj[i] = oldObj[i]
}
}
return obj;
}
這樣就能處理一個嵌套了Object和Array等復雜變數的物件,但是物件中還可能包含Date和RegExp物件、Set、Map……
Lodash庫
const lodash = require('lodash')
let newObj = lodash.cloneDeep(obj)
陣列的復制
let arr = [1, 2, 3, [4, 5], {a: 1}]
let copy = arr
copy.push(6)
let copy1 = [...arr]
copy1.push(999)
let copy2 = Array.from(arr)
copy2.push(888)
let copy3 = arr.slice()
copy3.push(777)
// 以上方法都是淺拷貝
arr[4].a = 2
console.log(arr) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6 ]
console.log(copy1) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6, 999 ]
console.log(copy2) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6, 888 ]
console.log(copy3) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6, 777 ]
參考連接
- 摸索 JS 內深拷貝的最佳實踐 - 簡單易懂的前端角 - SegmentFault 思否
- 理解JavaScript:不可變的原始值與可變的物件參考
- [ JS 進階 ] 基本型別 參考型別 簡單賦值 物件參考 - kraaas前端博客 - SegmentFault 思否
- 什么是js深拷貝和淺拷貝及其實作方式
- js 深拷貝 vs 淺拷貝 - 掘金
- 深拷貝的終極探索(99%的人都不知道) - 顏海鏡 - SegmentFault 思否
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/177003.html
標籤:JavaScript
下一篇:JS倒計時
