← Назад к вопросам
Как сделать копию объекта с вложенностями?
2.0 Middle🔥 221 комментариев
#JavaScript Core#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Глубокое копирование объектов с вложенностями
Это одна из классических задач в JavaScript. Проблема в том, что при поверхностном копировании (присваивание или spread оператор) копируются только ссылки на вложенные объекты и массивы, а не сами данные.
Проблема поверхностного копирования
const original = {
name: "John",
address: {
city: "Moscow",
coords: { lat: 55.7558, lng: 37.6173 }
},
hobbies: ["reading", "coding"]
};
// Неправильно: поверхностное копирование
const shallow = { ...original };
shallow.address.city = "SPB"; // Изменит и original!
console.log(original.address.city); // "SPB" — БУГ!
Решение 1: JSON.parse + JSON.stringify
Наиболее простой способ для обычных объектов:
const deep = JSON.parse(JSON.stringify(original));
deep.address.city = "SPB";
console.log(original.address.city); // "Moscow" — OK!
Плюсы:
- Простой синтаксис
- Встроено в язык
- Работает с вложенностью любой глубины
Минусы:
- Не копирует
undefined, функции,Symbol,Date(они теряются) - Круговые ссылки вызывают ошибку
- Медленнее других методов
Решение 2: Рекурсивная функция
Для более сложных случаев с функциями и датами:
function deepClone(obj, weakMap = new WeakMap()) {
// Базовые типы
if (obj === null || typeof obj !== "object") {
return obj;
}
// Обработка Date
if (obj instanceof Date) {
return new Date(obj.getTime());
}
// Обработка Array
if (Array.isArray(obj)) {
return obj.map(item => deepClone(item, weakMap));
}
// Защита от циклических ссылок
if (weakMap.has(obj)) {
return weakMap.get(obj);
}
// Обработка Object
const cloned = {};
weakMap.set(obj, cloned);
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloned[key] = deepClone(obj[key], weakMap);
}
}
return cloned;
}
const deep = deepClone(original);
deep.address.city = "SPB";
console.log(original.address.city); // "Moscow"
Преимущества:
- Сохраняет
Date, функции,undefined - Обрабатывает циклические ссылки через
WeakMap - Контролируемо
Решение 3: Структурированное клонирование (HTML5)
const deep = structuredClone(original);
Новый стандартный способ (ES2022), поддерживается в современных браузерах:
- Копирует Date, Map, Set, ArrayBuffer
- Автоматически обрабатывает циклы
- Не копирует функции и DOM элементы
Решение 4: Lodash
import _ from lodash;
const deep = _.cloneDeep(original);
Проверенная батарея, но добавляет зависимость.
Сравнение подходов
| Способ | Простота | Скорость | Функции | Дата | Циклы |
|---|---|---|---|---|---|
| JSON | ⭐⭐⭐ | ⭐⭐ | ❌ | ❌ | ❌ |
| Рекурсия | ⭐⭐ | ⭐⭐⭐ | ✅ | ✅ | ✅ |
| structuredClone | ⭐⭐⭐ | ⭐⭐⭐ | ❌ | ✅ | ✅ |
| Lodash | ⭐⭐⭐ | ⭐⭐ | ✅ | ✅ | ✅ |
Практический совет
Для 90% React приложений достаточно JSON решения. Если нужно сохранить функции или обработать циклы — используй structuredClone() или рекурсивную функцию.