В чем разница между глубоким (deep copy) и поверхностным (shallow copy) копированием

Ответ

Глубокое копирование создает полностью независимую копию объекта, включая все вложенные объекты. Поверхностное копирование создает новый объект, но вложенные объекты остаются ссылками на оригиналы.

Пример с поверхностным копированием:

const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
shallowCopy.b.c = 3; // изменит и оригинальный obj.b.c

Пример с глубоким копированием:

const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.b.c = 4; // не повлияет на оригинальный obj

Методы глубокого копирования: JSON.parse(JSON.stringify()), библиотеки типа Lodash (_.cloneDeep()), рекурсивное копирование. Для поверхностного: spread-оператор, Object.assign(), Array.slice().

Ответ 18+ 🔞

О, ну ты держись, сейчас я тебе такую простыню про копирование разложу, что ты офигеешь. Сидишь ты такой, пишешь код, и тут — бац! — нужно скопировать объект. А нихуя не всё так просто, дружище.

Вот представь: есть у тебя объект, как мешок с картошкой, а внутри мешка ещё один маленький мешочек с горохом. Так вот, поверхностное копирование — это как взять новый большой мешок и пересыпать в него картошку. Но маленький мешочек с горохом ты не пересыпаешь, ты просто берёшь и кладёшь в новый мешок тот же самый маленький мешочек. Один и тот же, ёпта! Ты в новом мешке гороху насыпешь — и в старом мешке его тоже станет больше, потому что мешочек-то один! Вот это пиздец, да?

const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
shallowCopy.b.c = 3; // ААА! И в оригинальном obj.b.c теперь тоже 3, блядь!

Вот так и живём. Сделал копию, думаешь — безопасно, а она тебе втихую оригинал ебёт.

А теперь глубокое копирование — это уже цирк с конями. Это когда ты берёшь и пересыпаешь ВСЁ. И картошку, и горох из маленького мешочка в новый маленький мешочек. Полная независимость, как США от Англии, только без чая в океане.

Самый народный способ, конечно, вот этот угарный костыль:

const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.b.c = 4; // Вот теперь всё чики-пуки, оригинал obj.b.c остался 3, иди нахуй.

Работает? Работает. Но это как молотком гвозди забивать — универсально, но не всегда изящно. Если там функции или undefined с Infinity — JSON сдохнет, как муха на стекле.

Есть ещё библиотеки, типа Lodash, у них там _.cloneDeep() — это уже профессиональный инструмент, как швейцарский нож. А можно и самому рекурсивно написать, но это уже для мазохистов, которые любят боль и страдания.

Короче, запомни, как "Отче наш": если нужно просто новый внешний контейнер — spread-оператор, Object.assign() или Array.slice(). А если нужно, чтобы всё внутри было независимым и не ебало мозг — тогда глубокое копирование, и да пребудет с тобой сила.