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