簡體   English   中英

使用 immer 在 JavaScript 中深度復制對象

[英]DeepCopy Object in JavaScript using immer

我正在使用immer來轉換 react/redux 狀態。 我也可以使用 immer 來深度復制一個對象而不轉換它嗎?

import produce, {nothing} from "immer"



const state = {
    hello: "world"
}

produce(state, draft => {})
produce(state, draft => undefined)
// Both return the original state: { hello: "world"}

這是來自官方的 immer README。 這是否意味着傳遞一個空函數來produce返回原始狀態或實際上原始狀態的深層副本?

非常感謝您的幫助 :)!

這很容易測試

import { produce } from 'immer'

const state = {
  hello: 'world',
}

const nextState = produce(state, draft => {})

nextState.hello = 'new world'
console.log(state, nextState)

哪個輸出

Object { hello: "new world" }

Object { hello: "new world" }

這意味着它不會創建對象的深層副本。

更新:

所以我很感興趣並經常測試了圖書館,這是我的發現。

我上面寫的代碼片段只是庫中的一個優化,如果沒有進行任何更改,它將返回舊狀態。 但是,如果進行一些更改,那么庫將按預期開始運行,之后的變異將無法實現。 那是,

const state = {
  hello: 'world',
}

const nextState = produce(state, draft => {
  draft.hello = 'new world';
})

nextState.hello = 'newer world';

console.log(state, nextState)

將導致錯誤: TypeError: "world" is read-only

這意味着你的newState是不可變的,你不能再對其執行突變。

我發現另一個相當有趣的事情是immer在使用class實例時失敗了。 那是,

class Cls {
  prop = 10;
}

const instance = new Cls();

const obj = {
  r: instance,
};

const newObj = produce(obj, draft => {
  draft.r.prop = 15;
});

console.log(obj, newObj);

結果是

r: Object { prop: 15 }

r: Object { prop: 15 }

因此,要回到最初的問題,您是否可以通過更改草稿中的任何內容來獲取初始Object的深層副本。 不,你不能,即使你做了(通過更改創建的屬性只是為了愚弄immer),生成的克隆對象將是不可變的,並沒有真正的幫助。

解決方案:Immer 的產品僅在更新時提供一個新的深度克隆對象。 您可以創建自己的生產功能,其行為與 immer 的生產功能類似,但每次使用 loadash 都會提供一個克隆對象

import _ from 'lodash';
export default function produceClone(object, modifyfunction) {
    let objectClone = _.cloneDeep(object);
    if (!modifyfunction) return objectClone;
    modifyfunction(objectClone);
    return objectClone;
    }

無論您是否修改對象,這每次都會為您提供一個 deepCloned(或深度復制)對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM