Как скопировать объект или массив
Поверхностная копия (только верхний уровень) — оператор ..., глубокая (вместе со всеми вложенными объектами) — structuredClone:
const user = { name: "Аня", marks: [5, 4] };
const shallow = { ...user };
const deep = structuredClone(user);structuredClone есть во всех современных браузерах и в Node.js 17 и новее.
Почему присваивание не копирует
Переменная хранит не сам объект, а ссылку на него. const copy = user — вторая ссылка на тот же объект:
const user = { name: "Аня" };
const copy = user;
copy.name = "Лена";
console.log(user.name);ЛенаИзменение через copy видно и через user: объект один.
Поверхностная и глубокая копия
{ ...user } и Object.assign({}, user) создают новый объект, но копируют только верхний уровень. Вложенные объекты и массивы остаются общими:
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 копирует всё до самого дна:
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:
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 не копирует
- Функции. Объект с методом вызовет ошибку
DataCloneError. - Элементы страницы (DOM) — тоже ошибка.
- Классы. Копия экземпляра класса — обычный объект: свойства на месте, а методы класса пропадают.
Для таких объектов копию собирают вручную или через конструктор класса.