Что такое поверхностная копия объекта?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое поверхностная копия объекта?
Поверхностная копия (shallow copy) — это создание нового объекта, в котором копируются только значения первого уровня вложенности. Если объект содержит вложенные объекты или массивы, копируются только ссылки на них, а не сами вложенные структуры. Это важное различие, которое часто вызывает ошибки в JavaScript.
Неглубокая копия vs Глубокая копия
Неглубокая копия (Shallow Copy):
const original = {
name: "Алиса",
age: 25,
address: { city: "Москва", street: "Ленина" }
};
const shallow = Object.assign({}, original);
// или
const shallow = { ...original };
shallow.name = "Боб"; // Изменяет shallow, не original
shallow.address.city = "СПб"; // Изменяет ОБА объекта!
console.log(original.address.city); // "СПб" — МЕНЯЕТСЯ!
Глубокая копия (Deep Copy):
const deep = JSON.parse(JSON.stringify(original));
deep.address.city = "СПб"; // Изменяет только deep
console.log(original.address.city); // "Москва" — НЕ меняется
Способы создания поверхностной копии
1. Спред оператор (...):
const original = { a: 1, b: { c: 2 } };
const copy = { ...original };
copy.a = 10; // original.a остаётся 1
copy.b.c = 20; // original.b.c становится 20 (проблема!)
2. Object.assign():
const original = { a: 1, b: { c: 2 } };
const copy = Object.assign({}, original);
copy.a = 10; // original.a остаётся 1
copy.b.c = 20; // original.b.c становится 20 (проблема!)
3. Array.slice() для массивов:
const original = [1, 2, [3, 4]];
const copy = original.slice();
copy[0] = 10; // original[0] остаётся 1
copy[2][0] = 30; // original[2][0] становится 30 (проблема!)
4. Array.concat() для массивов:
const original = [1, 2, { value: 3 }];
const copy = [].concat(original);
copy[2].value = 30; // Влияет на original (проблема!)
Визуализация проблемы
const original = {
user: "Alice",
settings: {
theme: "dark",
notifications: true
}
};
const shallow = { ...original };
// Уровень 1 (примитивный тип)
shallow.user = "Bob"; // ✅ Независимо копировано
console.log(original.user); // "Alice"
// Уровень 2+ (объект)
shallow.settings.theme = "light"; // ❌ Общая ссылка
console.log(original.settings.theme); // "light" (меняется!)
// Почему?
// original.settings и shallow.settings указывают на ОДИН объект
console.log(original.settings === shallow.settings); // true
Когда использовать поверхностную копию
React и Redux:
// Хорошо для простых данных
const newState = { ...oldState, loading: false };
// Проблема с вложенными объектами
const newState = {
...oldState,
user: { ...oldState.user, name: "New Name" } // Нужна копия и user
};
Примеры в React:
const [user, setUser] = useState({
name: "Alice",
profile: { age: 25, city: "Moscow" }
});
// ❌ Проблема: изменит исходный объект
user.profile.age = 26;
setUser(user);
// ✅ Правильно: shallow copy для первого уровня
setUser({ ...user, profile: { ...user.profile, age: 26 } });
// ✅ Или используй immer библиотеку
Практические решения
1. JSON парсер (для простых данных без функций):
const original = { a: 1, b: { c: 2 } };
const deep = JSON.parse(JSON.stringify(original));
deep.b.c = 20;
console.log(original.b.c); // 2 (не меняется)
// Проблема: теряют функции, Map, Set, undefined
2. Структурированное клонирование (новый API):
const original = { a: 1, b: { c: 2 } };
const deep = structuredClone(original);
deep.b.c = 20;
console.log(original.b.c); // 2
// Поддерживает функции, Date, Map, Set
3. Lodash (для сложных случаев):
import _ from lodash;
const original = { a: 1, b: { c: 2 } };
const deep = _.cloneDeep(original);
Правило большого пальца
// Используй shallow copy когда:
// - Только примитивные значения на первом уровне
const config = { debug: true, timeout: 5000 };
const copy = { ...config }; // ✅ Безопасно
// Используй deep copy когда:
// - Есть вложенные объекты или массивы
const user = {
name: "Alice",
preferences: { theme: "dark" }
};
const copy = structuredClone(user); // ✅ Безопасно
Понимание различия между поверхностной и глубокой копией — критично для избежания неуловимых багов в JavaScript приложениях, особенно в React и других фреймворках.