Способы клонирования Object в JavaScript

Здесь рассмотрим некоторые известные решения для клонирования объектов в JavaScript.

  1. ES6
  2. JS-библиотеки
  3. JSON.parse и JSON.stringify
  4. Нативные методы

Решения ES6

ES6 предлагает два механизма поверхностного копирования:

Примечание. Поверхностная копия – побитовая копия объекта. Создается новый объект, который имеет точную копию значений в исходном объекте. Если какие-либо поля объекта являются ссылками на другие объекты, копируются только ссылочные адреса.

Object.assign()

Метод Object.assign() копирует все перечисляемые собственные свойства из одного или нескольких исходных объектов в целевой объект. Возвращает целевой объект.

В примере рассмотрим новый целевой объект {} и два источника (исходных объекта). Объединим исходное состояние и новое с измененным значением в username.

const state = {
  username: 'test',
  password: '123456'
};
console.log(Object.assign({}, state, {username: 'dev'}));
// {username: 'dev', password: '123456'}

Spread syntax

Когда работаете с управлением состояниями, особенно в Angular или Redux, часто можете увидеть этот синтаксис.

Пример:

const state = {
  username: 'test',
  password: '123456'
};
const data = { ...state };
console.log(data);
// {username: 'test', password: '123456'}

Библиотеки

Иногда люди используют различные Javascript-библиотеки, такие как jQuery, Lodash и Underscore, для различных целей:

  • Внедрить что-то быстро, чтобы уложиться в срок
  • Лет 10 лет назад, был сверх-популярен jQuery
  • Навыки разработчика. Может применять какие-то вещи, основываясь на своих знаниях, это не лучший вариант, но тоже бывает
  • Рабочий процесс компании, потому что в некоторых компаниях есть чёткие требования к библиотекам для использования в старом и новом проектах.

Но давайте посмотрим, какие библиотеки и как можно использовать для клонирования объекта в JavaScript.

jQuery

jQuery.extend(): объединит содержимое двух или более объектов вместе в первый объект.

const object1 = {
  apple: 0,
  banana: {weight: 5, price: 10},
  cherry: 97
};
const object2 = {
  banana: {weight: 12},
  durian: 101
};
const object3 = jQuery.extend({}, object1, object2);
console.log(object3);
// {apple: 0, banana: {weight: 12}, cherry: 97, durian: 101}

Ещё в jQuery есть метод .clone() для глубокой копии элемента.

Lodash

Вы можете использовать _.clone() и _.cloneDeep() в lodash для мелкого и глубокого копирования.

const objects = [{'a': 1}, {'b': 2}];
const object1 = _.clone(objects);
const object2 = _.cloneDeep(objects);

Underscore

Underscore предлагает вам множество функциональных помощников. Для объектов есть метод _.clone().

Этот метод реализует поверхностно скопированный клон предоставленного простого объекта. Для любых вложенных объектов или массивов будут скопированы только ссылки.

Clone

Эту библиотеку можно использовать для клонирования не только объектов (object) JavaScript, а ещё: array, number, string, map, set, promise.

Clone прост в установке и использовании. Можно прочитать README.md, чтобы узнать, как его использовать.

JSON.parse и JSON.stringify

Метод JSON.parse() анализирует строку JSON, создавая значение JavaScript или объект, описываемый этой строкой.

Метод JSON.stringify() преобразует объект или значение JavaScript в строку JSON.

Однако эти методы можно использовать для глубокого клонирования объекта с помощью простого синтаксиса JSON.parse(JSON.stringify(object)).

У такого метода есть ряд ограничений. Его лучше использовать с простыми значениями, со строковыми или JSON-типами:

  • Он не клонирует функции (все должно сериализоваться в тип данных JSON)
  • Он не работает с типом Date. JSON.stringify(new Date()) вернёт строковое представление даты в формате ISO, которое JSON.parse() уже не преобразует обратно в объект Date.
  • Медленно клонирует объект со сложными типами: undefined, Infinity, RegExp, Map, Set, Blob, FileList, Image, Array.

Нативные методы

Serialization API предоставляет средства для сериализации значений JavaScript способом, совместимым с алгоритмом структурированного клонирования HTML. Используется в среде node.js.

const v8 = require('v8');

const structuredClone = obj => {
  return v8.deserialize(v8.serialize(obj));
};