Поверхностное и глубокое копирование объектов
Частый практический вопрос: «Как скопировать объект, чтобы не задеть оригинал?»
Поверхностная копия дублирует только верхний уровень; вложенные объекты остаются общими ссылками. Глубокая копия рекурсивно копирует всё.
Поверхностная копия делит вложенное
spread и Object.assign копируют только верхний уровень. Вложенный объект — это та же ссылка, поэтому его мутация видна в обеих копиях.
const original = { name: "Аня", address: { city: "Москва" } };
const shallow = { ...original };
shallow.name = "Боря"; // верхний уровень — независим
shallow.address.city = "Казань"; // вложенное — общее!
console.log(original.name); // не изменилось
console.log(original.address.city); // изменилось!
Вывод:
Аня Казань
Это классический баг: думали, что скопировали объект целиком, а на деле два «клона» делят вложенную структуру.
Глубокая копия через JSON
Простой способ глубокой копии — сериализовать в JSON и обратно. Тогда копируется вся структура целиком.
const original = { name: "Аня", address: { city: "Москва" } };
const deep = JSON.parse(JSON.stringify(original));
deep.address.city = "Казань";
console.log(original.address.city); // оригинал цел
console.log(deep.address.city);
Вывод:
Москва Казань
Ограничения JSON-копии
Способ через JSON не идеален: он теряет функции, undefined, Symbol, превращает Date в строку и падает на циклических ссылках. Это любят спросить «а в чём подвох».
const obj = {
fn: () => 1,
value: undefined,
when: new Date(0),
num: 5,
};
const copy = JSON.parse(JSON.stringify(obj));
console.log("fn" in copy); // функция потеряна
console.log("value" in copy); // undefined потеряно
console.log(typeof copy.when); // Date стала строкой
console.log(copy.num);
Вывод:
false false string 5
Современный способ: structuredClone
В современных средах есть встроенный structuredClone(obj) — он делает глубокую копию, поддерживает Date, Map, Set и циклические ссылки (но не копирует функции). На собеседовании достаточно упомянуть его как правильный современный вариант.
Памятка
| Способ | Глубина | Подвох |
{...obj} | поверхностная | вложенное общее |
JSON.parse(JSON.stringify) | глубокая | теряет функции, Date→строка |
structuredClone | глубокая | не копирует функции |
Итог
- Поверхностная копия делит вложенные объекты — мутация видна в оригинале.
JSON.parse(JSON.stringify)делает глубокую копию, но теряет функции и Date.- Современный правильный вариант —
structuredClone.