Deep clone объекта
Создание полной независимой копии объекта — изменения в клоне не влияют на оригинал.
Задача
Нужно скопировать вложенный объект или массив так, чтобы изменения в копии не затрагивали исходный объект. Обычный spread { ...obj } копирует только первый уровень.
Решение
Способ 1 — structuredClone (современный, рекомендуемый)
const original = {
name: 'Alice',
address: { city: 'Moscow', zip: '101000' },
tags: ['js', 'css'],
};
const clone = structuredClone(original);
clone.address.city = 'SPb';
clone.tags.push('html');
console.log(original.address.city); // 'Moscow' — не изменился
console.log(original.tags); // ['js', 'css'] — не изменился
structuredClone поддерживает Date, Map, Set, ArrayBuffer, но не клонирует функции и undefined-поля.
Способ 2 — JSON.parse(JSON.stringify(obj)) (простой фоллбэк)
const clone = JSON.parse(JSON.stringify(original));
Ограничения: теряет Date (превращает в строку), undefined, функции, Symbol, Map, Set, циклические ссылки бросают ошибку.
Способ 3 — рекурсивная функция (полный контроль)
function deepClone(value) {
if (value === null || typeof value !== 'object') return value;
if (value instanceof Date) return new Date(value);
if (Array.isArray(value)) return value.map(deepClone);
return Object.fromEntries(
Object.entries(value).map(([k, v]) => [k, deepClone(v)])
);
}
Ключевые моменты
structuredClone— лучший выбор в 2024+, поддерживается во всех современных браузерах и Node 17+.JSON.parse/stringify— быстро, но теряет типы; используй только для простых JSON-данных.{ ...obj }иObject.assign— поверхностные копии, вложенные объекты остаются общими.- Циклические ссылки:
structuredCloneобрабатывает,JSON.stringify— бросаетTypeError.
Варианты
- Lodash
_.cloneDeep(obj)— надёжный, обрабатывает все edge cases; добавляет зависимость. - Immer — для иммутабельного обновления вложенных объектов в стейте.
Когда НЕ использовать
- Если нужно просто обновить поля первого уровня — достаточно spread:
{ ...obj, name: 'Bob' }. - Для клонирования классов с методами —
structuredCloneне копирует prototype, нужна ручная реализация.