Как правильно клонировать объект JavaScript? - PullRequest
2787 голосов
/ 08 апреля 2009

У меня есть объект, x. Я хотел бы скопировать его как объект y, чтобы изменения в y не изменяли x. Я понял, что копирование объектов, полученных из встроенных объектов JavaScript, приведет к появлению дополнительных нежелательных свойств. Это не проблема, так как я копирую один из своих объектов, созданных в буквальном смысле.

Как правильно клонировать объект JavaScript?

Ответы [ 63 ]

0 голосов
/ 24 февраля 2018

Если вы используете TypeScript, вам нужно поддерживать старые веб-браузеры (и поэтому не можете использовать Object.assign) и не используете библиотеку со встроенным методом клонирования, вы можете сделать себя помощником combine в несколько строк кода. Он объединяет объекты, и если у вас есть только один, просто клонируйте его.

/** Creates a new object that combines the properties of the specified objects. */
function combine(...objs: {}[]) {
    const combined = {};
    objs.forEach(o => Object.keys(o).forEach(p => combined[p] = o[p]));
    return combined;
}
0 голосов
/ 16 июня 2019

Так же, как эта ссылка говорит, используйте этот код:
let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));

0 голосов
/ 12 июля 2016

Для обработки круговых объектов, которые не могут обрабатывать JSON.stringify, вы можете добавить библиотеку с именем JSOG , которая сериализует и десериализует произвольные графы в формат JSON.

var clone = JSOG.parse(JSOG.stringify(original));

Также было бы интересно попробовать залатать JSOG для клонирования с помощью этого трюка (на данный момент не хватает времени, но если кто-то захочет дать ему шанс ...):

Сериализация простой функции:

foo.f = function(a) { return a }
var stringForm = foo.f.toString() // "function (a) { return a }"

Десериализация функции:

eval("foo.f = " + stringForm)

Потребуются некоторые соглашения (вероятно, в названии свойства) для идентификации функций по сравнению с обычными строками (возможно, @func_f).

Конечно, если функция вызывает вторую функцию, вторая функция должна существовать так же, как и для оригинала.

Вышеприведенное, однако, довольно опасно, если вы хотите принять сериализованную форму из ненадежного источника, но тогда принятие любой функции в любой форме из ненадежного источника будет опасным, поэтому, если вы заинтересованы в клонировании функций, доверие должно иметь уже установлено (или вы уже намереваетесь написать уязвимость в системе безопасности!).

Отказ от ответственности: Я не тестировал скорость JSOG stringify / parse против JSON stringify / parse, но он работает на простых (круговых) объектах, с которыми я его тестировал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...