1. 程式人生 > 實用技巧 >Js實現深淺複製

Js實現深淺複製

為什麼有深複製、淺複製?

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].const
ructor === 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)

資源搜尋網站大全 https://www.renrenfan.com.cn 廣州VI設計公司https://www.houdianzi.com

陣列的複製

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 ]
console.log(copy2) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6, 888 ]
console.log(copy3) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6, 777 ]