Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Глубокое копирование в JavaScript
Глубокое копирование — это создание нового объекта со всеми вложенными структурами данных, скопированными полностью, а не по ссылке. Это критично при работе с состоянием в React и сложными объектами.
Почему это нужно
// Проблема: поверхностное копирование
const original = { user: { name: "John", age: 30 } };
const copy = { ...original }; // Shallow copy
copy.user.name = "Jane";
console.log(original.user.name); // "Jane" — original изменился!
Вложенные объекты остаются ссылками, а не копируются.
Решение 1: JSON метод (простой, но с ограничениями)
const original = {
name: "John",
hobbies: ["reading", "coding"],
address: { city: "New York", zip: "10001" }
};
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.address.city = "Boston";
console.log(original.address.city); // "New York" — оригинал не изменился
Преимущества:
- Просто и понятно
- Работает для большинства объектов
Недостатки:
- Теряются методы и функции
- Теряются Symbol и undefined
- Не работает с Date, Map, Set, RegExp
const data = {
date: new Date(),
copy: JSON.parse(JSON.stringify(data));
};
console.log(copy.date); // Строка, не Date объект!
Решение 2: Рекурсивная функция (универсальное)
function deepCopy(obj) {
// Базовые типы
if (obj === null || typeof obj !== "object") return obj;
// Специальные объекты
if (obj instanceof Date) return new Date(obj.getTime());
if (obj instanceof Map) return new Map(obj);
if (obj instanceof Set) return new Set(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// Массивы
if (Array.isArray(obj)) {
return obj.map(item => deepCopy(item));
}
// Обычные объекты
const copy = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
const original = {
name: "John",
hobbies: ["reading", "coding"],
createdAt: new Date(),
tags: new Set(["js", "frontend"])
};
const copy = deepCopy(original);
copy.tags.add("react");
console.log(original.tags); // Set(2) { 'js', 'frontend' }
Решение 3: structuredClone (современный стандарт)
const original = {
name: "John",
hobbies: ["reading", "coding"],
createdAt: new Date()
};
const copy = structuredClone(original);
copy.hobbies.push("gaming");
copy.createdAt.setFullYear(2025);
console.log(original.hobbies); // ["reading", "coding"]
console.log(original.createdAt); // 2026-04-02
Преимущества:
- Встроенный метод браузера
- Работает с Date, Map, Set, Blob и др.
- Самый надёжный вариант
Недостатки:
- Может быть медленнее на больших объектах
- Не копирует функции
Решение 4: Lodash (если нужна сложная логика)
import _ from "lodash";
const original = { user: { name: "John" } };
const copy = _.cloneDeep(original);
В контексте React
function UserProfile() {
const [state, setState] = useState({
user: { name: "John", address: { city: "NY" } }
});
const handleCityChange = (newCity) => {
// Правильно: создаём новый объект
const newState = structuredClone(state);
newState.user.address.city = newCity;
setState(newState); // React заметит изменение
};
return (
<button onClick={() => handleCityChange("LA")}>
Сменить город
</button>
);
}
Сравнение методов
| Метод | Простота | Универсальность | Скорость |
|---|---|---|---|
| JSON | Высокая | Низкая | Высокая |
| structuredClone | Высокая | Высокая | Средняя |
| Рекурсия | Средняя | Высокая | Низкая |
| Lodash | Высокая | Высокая | Средняя |
Рекомендация: Используй structuredClone как основной выбор в современных браузерах. Для старых браузеров или сложных случаев — рекурсивную функцию или Lodash.