Це бородате питання, яке досі задають на інтервʼю - зазвичай в компаніях, де люди явно засиділися і пропустили безліч оновлень в JS. В цілому є три найпоширеніші способи склонувати обʼєкт в JavaScript.
Spread оператор
Це найпростіший і найелегантніший спосіб. Єдиний нюанс в тому, що spread виконує shallow (поверхневе) клонування. Це означає, що всі вкладені обʼєкти не будуть склоновані і будуть посилатися на оригінальний обʼєкт.
const user = {
id: 1,
email: "test@test.com",
notifications: {
email: true
},
externalId: BigInt(232323345555),
};
const userClone = { ...user };
// Якщо ми змінимо значення поля user.notifications.email,
// то зміниться і userClone.notifications.email
// так як userClone.notifications не був склонований
// і фактично це просто посилання на user.notifications
user.notifications.email = false;
console.log(userClone.notifications.email); // false
JSON.stringify → JSON.parse
Старий дідівський метод, який робить deep clone (глибоке клонування) обʼєкта. Це означає, що всі вкладені обʼєкти будуть склоновані. В цілому цей спосіб робочий, але має одну проблему - він працює тільки з простими типами даних.
Якщо обʼєкт має поля з Map/Set, undefined, Infinity, BigInt і т.д., ми або отримаємо помилку, або поля будуть загублені чи конвертовані в рядок. Тому використовувати такий спосіб в реальному проєкті не найкраща ідея, і краще використовувати third party або спосіб, який я опишу далі.
const user = {
id: 1,
email: "test@test.com",
notifications: {
email: true
},
externalId: BigInt(232323345555),
};
// Так як externalId, це BigInt ми отримаємо помилку і клонування не відбудеться
const userClone = JSON.parse(JSON.stringify(user));
structuredClone
Це відносно новий метод в JS, який дозволяє робити глибоке клонування, в тому числі складних типів, з якими не справляється попередній метод. Він гарно розписаний в MDN, тому для детального розбору рекомендую прочитати документацію.
const user = {
id: 1,
email: "test@test.com",
notifications: {
email: true
},
externalId: BigInt(232323345555),
};
// Клонування буде успі
const user2 = structuredClone(user);