Здесь рассмотрим некоторые известные решения для клонирования объектов в JavaScript.
Решения 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));
};