← Назад к вопросам

Что такое поверхностная копия объекта?

1.2 Junior🔥 181 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое поверхностная копия объекта?

Поверхностная копия (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 и других фреймворках.