Как правильно клонировать объект в JavaScript?
Я имею объект x
и хотел бы создать его копию в виде объекта y
, чтобы изменения в y
не влияли на x
. Я заметил, что копирование объектов, производных от встроенных объектов JavaScript, приводит к появлению лишних, нежелательных свойств. Однако это не проблема, так как я копирую один из своих собственных объектов, созданных с помощью литералов.
Как правильно клонировать объект в JavaScript?
5 ответ(ов)
Конечно! Представьте, что у вас есть следующий объект, который вы хотите клонировать:
let obj = {a:1, b:2, c:3}; // ES6
или
var obj = {a:1, b:2, c:3}; // ES5
Ответ на этот вопрос в основном зависит от версии ECMAScript, которую вы используете. В ES6+
вы можете просто воспользоваться методом Object.assign
для клонирования:
let cloned = Object.assign({}, obj); // новый объект {a:1, b:2, c:3};
Или использовать оператор распространения (spread operator) следующим образом:
let cloned = {...obj}; // новый объект {a:1, b:2, c:3};
Однако если вы используете ES5
, у вас есть несколько методов для клонирования, и JSON.stringify
может оказаться полезным. Просто убедитесь, что вы не используете этот метод для больших объемов данных, так как это не самый оптимальный способ. Тем не менее, он может быть весьма удобным в ряде случаев, вот так:
let cloned = JSON.parse(JSON.stringify(obj));
// новый объект {a:1, b:2, c:3}; Это может быть удобно, но старайтесь избегать использования на больших объемах данных многократно.
Надеюсь, это поможет!
Обновление 6 июля 2020 года
Существует три (3) способа клонирования объектов в JavaScript. Поскольку объекты в JavaScript являются ссылочными значениями, просто скопировать их с помощью оператора = не получится.
Способы клонирования:
const food = { food: 'apple', drink: 'milk' }
// 1. Используя "Spread"
// ------------------
{ ...food }
// 2. Используя "Object.assign"
// ------------------
Object.assign({}, food)
// 3. "JSON"
// ------------------
JSON.parse(JSON.stringify(food))
// РЕЗУЛЬТАТ:
// { food: 'apple', drink: 'milk' }
Это может служить справочным резюме.
Один особенно неуклюжий способ сделать глубокие копии объектов, не имеющих методов, — это использовать JSON-кодирование. Методология заключается в том, чтобы сначала закодировать ваш целевой объект в формат JSON, а затем, декодируя его, получать необходимую копию. Вы можете декодировать столько раз, сколько нужно, чтобы создать необходимое количество копий.
Естественно, функции не могут быть представлены в формате JSON, поэтому данный метод будет работать только для объектов без методов.
Эта методология идеально подошла для моего случая, поскольку я храню JSON-объекты в хранилище ключ-значение, и когда они отображаются как объекты в JavaScript API, каждый объект фактически содержит копию исходного состояния, что позволяет нам вычислять дельту после того, как вызывающая сторона изменила доступный объект.
var object1 = {key: "value"};
var object2 = object1;
object2 = JSON.stringify(object1);
object2 = JSON.parse(object2);
object2.key = "a change";
console.log(object1); // возвращает "value"
Таким образом, если вам нужно сделать простую глубокую копию объекта без методов, данный подход может быть полезен. Однако следует помнить о его ограничениях и использовать его с осторожностью.
Чтобы склонировать объект в JavaScript, вы можете использовать оператор распространения (spread operator):
const objClone = { ...obj };
Однако будьте внимательны, так как вложенные объекты будут скопированы по ссылке. Это означает, что если вы измените вложенный объект в objClone
, изменения также отразятся в оригинальном объекте obj
. Если вам требуется глубокое клонирование, можете использовать такие методы, как JSON.parse(JSON.stringify(obj))
, или библиотеки, например, Lodash с функцией _.cloneDeep()
.
Функция clone
предназначена для глубокого копирования объекта. Рассмотрим ее работу подробнее:
function clone(obj) {
// Проверяем, является ли объект null или не объектом (например, примитивом)
if (obj == null || typeof(obj) != 'object')
return obj; // Если да, то просто возвращаем объект или примитив
// Создаем новый объект с таким же конструктором, как у исходного
var temp = new obj.constructor();
// Проходим по всем ключам исходного объекта
for (var key in obj)
// Рекурсивно вызываем функцию clone для каждого свойства
temp[key] = clone(obj[key]);
// Возвращаем новый объект
return temp;
}
Пояснение:
Проверка на
null
и тип: Сначала функция проверяет, не является ли переданный объектnull
и не является ли он примитивным типом (например, число или строка). Если это так, то просто возвращается оригинальный объект.Создание нового объекта: Если это объект, то создается новый объект того же типа с помощью
new obj.constructor()
.Рекурсивное копирование свойств: Затем с помощью цикла
for...in
функция проходит по всем свойствам исходного объекта и рекурсивно вызывает себя для каждого свойства, чтобы скопировать их значения.Возврат результата: Напоследок возвращается новый копируемый объект.
Таким образом, эта функция позволяет создать глубокую копию любого объекта, включая вложенные объекты. Однако стоит учесть, что она не справляется с такими случаями, как циклические ссылки и специфические объекты, как Date
, RegExp
и др.
Длина объекта в JavaScript
Как объединить свойства двух объектов JavaScript?
Как проверить, является ли объект массивом?
Как отобразить объект JavaScript?
Поиск объекта в массиве объектов JavaScript с совпадающим значением