Глиф Учебники

Как скопировать объект или массив

Справочник · JavaScript · 1 минута чтения

Поверхностная копия (только верхний уровень) — оператор ..., глубокая (вместе со всеми вложенными объектами) — structuredClone:

JavaScript
const user = { name: "Аня", marks: [5, 4] };

const shallow = { ...user };
const deep = structuredClone(user);

structuredClone есть во всех современных браузерах и в Node.js 17 и новее.

Почему присваивание не копирует

Переменная хранит не сам объект, а ссылку на него. const copy = user — вторая ссылка на тот же объект:

JavaScript
const user = { name: "Аня" };
const copy = user;

copy.name = "Лена";
console.log(user.name);
Вывод
Лена

Изменение через copy видно и через user: объект один.

Поверхностная и глубокая копия

{ ...user } и Object.assign({}, user) создают новый объект, но копируют только верхний уровень. Вложенные объекты и массивы остаются общими:

JavaScript
const user = { name: "Аня", marks: [5, 4] };

const shallow = { ...user };
shallow.name = "Лена";
shallow.marks.push(3);

console.log(user);
Вывод
{ name: 'Аня', marks: [ 5, 4, 3 ] }

Имя в оригинале осталось прежним, а массив оценок изменился: у user и shallow он один на двоих.

structuredClone копирует всё до самого дна:

JavaScript
const user = { name: "Аня", marks: [5, 4] };

const deep = structuredClone(user);
deep.marks.push(3);

console.log(user.marks);
console.log(deep.marks);
Вывод
[ 5, 4 ]
[ 5, 4, 3 ]

Для объектов без вложенности хватает { ...obj }. Если внутри есть объекты или массивы и копию будут менять — structuredClone.

Массивы

Для массивов то же самое: [...arr] или arr.slice() — поверхностная копия, structuredClone(arr) — глубокая.

Почему не JSON.parse(JSON.stringify())

Старый способ глубокой копии — перевести объект в JSON и обратно. Он теряет всё, чего нет в JSON:

JavaScript
const lesson = { title: "Урок", date: new Date(0), note: undefined };
const copy = JSON.parse(JSON.stringify(lesson));

console.log(typeof copy.date);
console.log("note" in copy);
Вывод
string
false

Дата стала строкой, свойство со значением undefined пропало, функции и NaN тоже не переживут такую копию. structuredClone сохраняет даты, undefined, Map и Set.

Что structuredClone не копирует

Для таких объектов копию собирают вручную или через конструктор класса.