Поиск по сайту
Ctrl + K
Вопросы по JS

Объясните разницу между поверхностным и глубоким копированием

Когда мы говорим о копировании объектов и массивов в JavaScript, существует два основных типа копирования: поверхностное копирование (shallow copy) и глубокое копирование (deep copy). Разница между ними заключается в том, как копируются вложенные объекты или массивы.

1. Поверхностное копирование (Shallow Copy)

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

Пример:

let original = {
  a: 1,
  b: [2, 3],
};

let shallowCopy = { ...original };  // Поверхностная копия
shallowCopy.a = 10;
shallowCopy.b[0] = 20;

console.log(original.a);  // 1 (изменение не затронуло свойство 'a')
console.log(original.b);  // [20, 3] (массив b был изменен, так как это ссылка)

В этом примере, хотя мы изменили свойство a в копии, изменения в массиве b отразились и на оригинале, потому что массив в JavaScript является ссылочным типом данных, и копия содержит ссылку на тот же массив, что и в оригинале.

Способы поверхностного копирования:

  • Оператор распространения (spread operator)
  • Метод Object.assign()
  • Методы массива (slice(), concat() и т.д.)

2. Глубокое копирование (Deep Copy)

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

Пример:

let original = {
  a: 1,
  b: [2, 3],
};

let deepCopy = JSON.parse(JSON.stringify(original));  // Глубокая копия
deepCopy.a = 10;
deepCopy.b[0] = 20;

console.log(original.a);  // 1 (изменение не затронуло свойство 'a')
console.log(original.b);  // [2, 3] (массив b не изменился)

В этом примере изменения, внесенные в массив b в глубокой копии, не повлияли на оригинальный массив, поскольку был выполнен настоящий клон всех вложенных объектов.

Способы глубокого копирования:

  • Использование JSON.parse() и JSON.stringify()
  • Рекурсивное копирование
  • Использование библиотек, например, Lodash с методом cloneDeep()

3. Ключевые отличия между поверхностным и глубоким копированием:

ОсобенностьПоверхностное копированиеГлубокое копирование
Копирование вложенных объектовСсылки на вложенные объекты сохраняются (не копируются)Все вложенные объекты и массивы копируются рекурсивно
Типы данныхРаботает с примитивными значениями и ссылочными объектамиРаботает с примитивами и копирует вложенные объекты и массивы
Изменения в копииИзменения в копии могут повлиять на вложенные данные в оригиналеИзменения в копии не повлияют на оригинальные данные
Используемые методыObject.assign(), spread-оператор, методы массиваJSON.parse()/JSON.stringify(), рекурсивные функции, сторонние библиотеки

Заключение

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

Выбор подходящего метода зависит от структуры данных и целей, которые вы преследуете при копировании.