В Javascript есть ли способ создать клон объекта с копированием при записи?

Проблема: я переписываю функцию, которая возвращает большой простой объект javascript. Исходный объект не должен изменяться вызывающими объектами. Функция в настоящее время вызывается сотнями абонентов.

Некоторые решения:

  • Вернуть глубокую копию объекта. Это текущее решение. Это плохо, потому что (а) объект очень большой и (б) в 90% случаев клон не нужен, потому что большинство вызывающих объектов не изменяют значение.
  • Вернуть ссылку на объект. Это плохо, потому что вызывающие смогут изменять исходный объект, чего я не хочу.
  • Верните ссылку с Object.freeze или чем-то подобным. Это могло бы сработать, если бы я мог гарантировать, что вызывающая сторона не попытается изменить возвращаемое значение. Но я не могу реально гарантировать это. Опять же, функция вызывается сотнями вызывающих объектов, и многие из них уже изменяют значение (клон).

Мне нужно решение для копирования при записи, которое имеет следующие два свойства:

  1. Возвращаемое значение функции является ссылкой на исходный объект, пока значение не будет изменено.
  2. После изменения значения оно становится глубоким клоном исходного объекта.

Я провел несколько тестов и могу реализовать это с помощью Javascript Proxy . Просто перехватите все операции, которые изменяют цель (например, set, deleteProperty, defineProperty и т. д.), чтобы отслеживать изменения. Затем перехватите get, чтобы вернуть ссылку, если не было внесено никаких изменений, и вернуть клон, если изменения были внесены. Прокси-сервер также должен быть глубоким прокси-сервером, чтобы прослушивать изменения во вложенных свойствах.

Хотя я могу реализовать это сам, мне было интересно, есть ли уже какие-либо реализации. Я бы предпочел не изобретать велосипед, если в этом нет необходимости. Совместимость с браузером хороша, но не обязательна.


person Some Guy    schedule 15.02.2020    source источник
comment
Похоже, cow это то, что вам нужно npmjs.com/package/cow   -  person artanik    schedule 15.02.2020
comment
@artanik хммм... выглядит многообещающе. Спасибо!   -  person Some Guy    schedule 16.02.2020
comment
Вы пробовали пакет immer   -  person Aswin    schedule 18.10.2020


Ответы (1)


Библиотека immer делает именно то, что вы описываете — реализует COW с использованием прокси-серверов JavaScript. Взгляните на документы здесь: https://immerjs.github.io/immer/

person Nir    schedule 08.05.2021