Об'єкти й масиви в змінних зберігаються за посиланням. const b = a - це не копія, а друге ім'я для того самого об'єкта.
Поверхнева копія копіює лише перший рівень. Вкладені об'єкти лишаються спільними:
const user = { name: 'Оля', address: { city: 'Київ' } };
const copy = { ...user }; // або Object.assign({}, user)
copy.name = 'Іра'; // user.name не змінився
copy.address.city = 'Львів'; // user.address.city теж став 'Львів'!
Глибока копія копіює всі рівні:
const deep = structuredClone(user);
deep.address.city = 'Одеса'; // user не зачеплено
structuredClone (вбудований у браузери й Node.js 17+) коректно копіює Date, Map, Set, вкладені масиви й навіть циклічні посилання. Не копіює функції, DOM-вузли й прототипи класів: екземпляр класу стане звичайним об'єктом.
Старий прийом JSON.parse(JSON.stringify(obj)) має купу обмежень: Date перетворюється на рядок, undefined, функції й Map зникають, циклічні посилання дають помилку.
На практиці глибока копія потрібна рідше, ніж здається: у React, Vue чи Redux змінений стан зазвичай будують поверхневими копіями лише тих гілок, що змінилися, - це й дешевше, і дозволяє швидко порівнювати посилання.