Различные методы для копирования объекта в JavaScript

Различные методы для копирования объекта в JavaScript

В этом посте мы обсудим различные методы для копирования объекта 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}}

или вы можете написать свою собственную функцию для глубокого копирования/клонирования.

Итог

  1. Помните, что объекты Javascript являются изменяемыми и хранятся по ссылке.
  2. Object.assign () или Spread syntax могут использоваться для копирования, но это будет поверхностная копия.
  3. JSON. stringify и JSON. могут быть использованы для глубокого копирования.
  4. Вы можете создать свою собственную функцию для глубокого копирования или использовать сторонние библиотеки, такие как load Lodash, Underscore и многие другие.


.

  • January 18, 2020