DeepCopy Object в JavaScript, используя immer - PullRequest
0 голосов
/ 05 марта 2019

Я использую immer для преобразования состояния реакции / редукции.Могу ли я также использовать 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 возвращает глубокую копию исходного состояния или фактически исходного состояния?

Большое спасибо за помощь:)!

1 Ответ

0 голосов
/ 05 марта 2019

Это легко проверить с помощью

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 }

Итак, чтобы вернуться к первоначальному вопросу, вы можете получить глубокую копию исходного Объекта, ничего не изменяя впроект.Нет, вы не можете, и даже если вы это сделали (изменив свойство, созданное просто для того, чтобы обмануть, возможно, immer), результирующий клонированный объект будет неизменным и не очень полезным.

...