Чем отличается поверхностное и глубокое копирование объекта?

👨‍💻 Frontend Developer 🟠 Может встретиться 🎚️ Средний
#JavaScript #Объекты #База JS

Краткий ответ

Поверхностное копирование копирует только верхний уровень свойств объекта. Если свойства содержат другие объекты, то копируются только ссылки на них. Глубокое копирование копирует все уровни вложенности, создавая полностью независимую копию.


Полный ответ

Разница между поверхностным и глубоким копированием — одна из важных тем в JavaScript. Понимание этой разницы помогает избежать многих ошибок.

Поверхностное копирование

Копирует только первый уровень свойств:

const original = { 
  name: 'Иван', 
  address: { city: 'Москва' } 
};
 
const shallow = { ...original };
// shallow.name — копия
// shallow.address — ссылка на тот же объект!

Глубокое копирование

Копирует все уровни вложенности:

const original = { 
  name: 'Иван', 
  address: { city: 'Москва' } 
};
 
const deep = structuredClone(original);
// deep.name — копия
// deep.address — тоже копия, новый объект

Главная разница

Поверхностное копирование

const user = { 
  name: 'Иван', 
  address: { city: 'Москва' } 
};
 
const shallow = { ...user };
shallow.address.city = 'Питер';
console.log(user.address.city); // 'Питер' — исходный объект изменился!

Глубокое копирование

const user = { 
  name: 'Иван', 
  address: { city: 'Москва' } 
};
 
const deep = structuredClone(user);
deep.address.city = 'Питер';
console.log(user.address.city); // 'Москва' — исходный объект не изменился

Простые примеры

Когда важно глубокое копирование

// Работа с формами
const defaultForm = {
  user: { name: '', age: 0 },
  settings: { theme: 'light' }
};
 
// Поверхностная копия — опасно!
const form1 = { ...defaultForm };
form1.user.name = 'Иван';
// Теперь defaultForm.user.name тоже 'Иван'!
 
// Глубокая копия — безопасно
const form2 = structuredClone(defaultForm);
form2.user.name = 'Петр';
// defaultForm не изменился

Способы копирования

Поверхностное

// Spread-оператор
const shallow1 = { ...original };
 
// Object.assign
const shallow2 = Object.assign({}, original);

Глубокое

// structuredClone (современный способ)
const deep1 = structuredClone(original);
 
// JSON-методы (с ограничениями)
const deep2 = JSON.parse(JSON.stringify(original));

Важные моменты

1. Производительность

// Поверхностное — быстро
const shallow = { ...obj };
 
// Глубокое — медленнее, особенно для больших объектов
const deep = structuredClone(obj);

2. Поддержка типов

// JSON-методы теряют функции, undefined, Symbol
const obj = { func: () => {}, undef: undefined };
const copy = JSON.parse(JSON.stringify(obj));
// copy.func и copy.undef исчезнут!
 
// structuredClone сохраняет все типы
const copy2 = structuredClone(obj);
// Все данные сохранены

Частые ошибки

1. Неправильный выбор метода

// ❌ Используем поверхностное для вложенных объектов
const config = { database: { host: 'localhost' } };
const copy = { ...config };
copy.database.host = 'remote';
console.log(config.database.host); // 'remote' — неожиданно!
 
// ✅ Используем глубокое копирование
const copy2 = structuredClone(config);
copy2.database.host = 'remote';
console.log(config.database.host); // 'localhost' — правильно

2. Использование JSON-методов с функциями

// ❌ JSON-методы не работают с функциями
const obj = { method: () => {} };
const copy = JSON.parse(JSON.stringify(obj));
// copy.method исчезнет!
 
// ✅ Используем structuredClone
const copy2 = structuredClone(obj);
// Все данные сохранены

Простые правила

  1. Поверхностное — для простых объектов без вложенных ссылок
  2. Глубокое — для сложных структур с вложенными объектами
  3. structuredClone — современный и надежный способ глубокого копирования
  4. JSON-методы — быстрые, но с ограничениями
  5. Осторожно с производительностью — глубокое копирование медленнее

Понимание разницы между поверхностным и глубоким копированием помогает писать предсказуемый код и избегать ошибок с ссылками.


Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪