Перейти к основному содержимому

Копирование

Полезные способы копирования объектов:

Object.assign

const colors5 = Object.assign(colors, {
red: 'red', // переписываем поле
white: '#fff', // создаём новое
});

Сравнение копий объектов

const colors = {
red: '#F00',
green: '#0F0',
blue: '#00F',
};

const colors2 = colors;
const colors3 = new Object(colors);
const colors4 = { ...colors }; // Современный способ копирования (без side-effect)

// можно добавлять новые свойства
const colors5 = {
...colors,
white: '#fff',
black: '#000',
};

Прямое сравнение объектов (side-effect)

colors === colors2; // true - храняться по одной ссылке
colors === colors3; // true - храняться по одной (new Object)
colors === colors4; // false - через spread оператор (...)

Через Object.is

Object.is(colors, colors2); // true
Object.is(colors, colors3); // true
Object.is(colors, colors4); // false

Общая ссылка у объектов

const colors = {
red: '#F00',
green: '#0F0',
blue: '#00F',
};

const colors2 = colors;
colors2.red = 'red';

colors2.red; // 'red' - меняем у копии
colors.red; // 'red' - поменялось и у ссылки

Чтобы такого не возникало нужно клонировать объекты через spread оператор или structuredClone.


Поверхностная копия (shallow) - spread

Spread и Object.assign копируют только верхний уровень. Вложенные объекты и массивы остаются общими по ссылке.

const user = {
name: 'Jack',
skills: ['js', 'react'],
};

const copy = { ...user };

copy === user; // false
copy.skills === user.skills; // true (вложенныйh массив общий)

copy.skills.push('node');

copy.skills; // [ 'js', 'react', 'node' ]
user.skills; // ['js', 'react', 'node']

Можно исправить через spread на каждом уровне

const copy = {
...user,
skills: [...user.skills],
};

Глубокое копирование - structuredClone

structuredClone делает глубокую копию данных и разрывает общие ссылки. Подходит для объектов, массивов, Map, Set, Date и т.д.

const user = {
name: 'Jack',
skills: ['js', 'react'],
};

const deepCopy = structuredClone(user);

deepCopy.skills === user.skills; // false
deepCopy.skills.push('node');

deepCopy.skills; // [ 'js', 'react', 'node' ]
user.skills; // ['js', 'react']