В этом посте мы обсудим различные методы для копирования объекта JavaScript и выявим результаты каждого метода.
Но перед этим просто помните, что объекты JavaScript изменчивы по своей природе и хранятся в качестве ссылки. Поэтому, когда вы назначаете объект другой переменной, вы просто назначаете адрес памяти объекта этой переменной.
В этом случае ваш старый и новый объект будут указывать на один и тот же адрес памяти. Любое изменение в одном объекте будет отражено в другом. Так что просто присвоение одного объекта другому не будет действительно копировать ваш объект.
// Define object bar
var bar = {
x : 'Hi'
}
console.log(bar.x); //Hi
// Assign it to foo
var foo = bar;
console.log(foo.x); //Hi
//But
foo.x = 'Hello!! Im foo.';
console.log(foo.x); //Hello!! Im foo.
console.log(bar.x); //Hello!! Im foo.
bar.x = "Nice to meet you foo!!";
console.log(foo.x); //Nice to meet you foo!!
console.log(bar.x); //Nice to meet you foo!!Как вы видите в приведенном выше примере, и foo, и bar отражают изменения, сделанные в любом объекте.
Предоставляем вашему вниманию 3 метода, которые вы можете использовать для копирования объекта.
Поверхностное копирование с использованием Spread Syntax или Object.assign
Spread Syntax – Синтаксис распространения
Это самый короткий и простой способ скопировать/объединить объект. Например:
var obj = { foo: "foo", bar: "bar" };
var clonedObj = { ...obj };
// Object { foo: "foo", bar: "bar" }Object.assign
Метод Object.assign() можно использовать для копирования значений всех перечисляемых собственных свойств из одного или нескольких исходных объектов в целевой объект, и он вернет целевой объект.
var obj = { foo: "foo", bar: "bar" };
var clonedObj = Object.assign({}, obj);
// Object { foo: "foo", bar: "bar" }Использование синтаксиса распространения или Object. assign () – это стандартный способ копирования объекта в JavaScript. Обе методологии могут быть эквивалентно использованы для копирования/объединения перечислимых свойств объекта в другой объект.
Проблема с этими двумя подходами состоит в том, что они просто сделают поверхностную копию. Поверхностная копия – побитовая копия объекта. То есть создается новый объект, который имеет точную копию значений в исходном объекте. Но если любое из полей объекта является ссылкой на другие объекты, копируются только ссылочные адреса, то есть копируется только адрес памяти. Изменение такого поля ссылки будет отражено в обоих объектах. Смотрите пример ниже.
let obj = { a: 0 , b: { c: 0}};
let copySpread = {...obj};
let copyOA = Object.assign({}, obj);
console.log(JSON.stringify(obj)); // { a: 0, b: { c: 0}}
obj.a = 1;
console.log(JSON.stringify(obj)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(copySpread)); // { a: 0, b: { c: 0}}
console.log(JSON.stringify(copyOA)); // { a: 0, b: { c: 0}}
copySpread.a = 2;
console.log(JSON.stringify(obj)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(copySpread)); // { a: 2, b: { c: 0}}
console.log(JSON.stringify(copyOA)); // { a: 0, b: { c: 0}}
copyOA.a = 3;
console.log(JSON.stringify(obj)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(copySpread)); // { a: 2, b: { c: 0}}
console.log(JSON.stringify(copyOA)); // { a: 3, b: { c: 0}}
obj.b.c = 4;
console.log(JSON.stringify(obj)); // { a: 1, b: { c: 4}}
console.log(JSON.stringify(copySpread)); // { a: 2, b: { c: 4}}
console.log(JSON.stringify(copyOA)); // { a: 3, b: { c: 4}}Таким образом, эти два метода являются полезными, но они не сработают, когда у вас есть вложенный объект для копирования.
Глубокое копирование с использованием JSON.stringify и JSON.parse
Глубокое копирование происходит, когда объект копируется вместе с объектами, на которые он ссылается. Это можно легко сделать, используя комбинацию JSON.stringify и JSON.parse для создания глубокой копии.
В этом методе мы сначала выполняем JSON.stringify () объект json и снова анализируем его, чтобы вернуть объект json. Метод JSON.parse () анализирует строку JSON и создает значение JavaScript или объект, описываемый этой строкой. Эти новые поля объекта будут иметь свой собственный адрес памяти и не будут зависеть от глубоко вложенных полей объекта.
Например, объект DeepClone не будет иметь никакого эффекта, если основной исходный объект obj изменен, и наоборот.
// Deep Clone
obj = { a: 0 , b: { c: 0}};
let deepClone = JSON.parse(JSON.stringify(obj));
obj.a = 5;
obj.b.c = 5;
console.log(JSON.stringify(obj)); // { a: 5, b: { c: 5}}
console.log(JSON.stringify(deepClone)); // { a: 0, b: { c: 0}}
deepClone.a = 6;
deepClone.b.c = 6;
console.log(JSON.stringify(obj)); // { a: 5, b: { c: 5}}
console.log(JSON.stringify(deepClone)); // { a: 6, b: { c: 6}}или вы можете написать свою собственную функцию для глубокого копирования/клонирования.
Итог
- Помните, что объекты Javascript являются изменяемыми и хранятся по ссылке.
- Object.assign () или Spread syntax могут использоваться для копирования, но это будет поверхностная копия.
- JSON. stringify и JSON. могут быть использованы для глубокого копирования.
- Вы можете создать свою собственную функцию для глубокого копирования или использовать сторонние библиотеки, такие как load Lodash, Underscore и многие другие.
