Кратко
Примитивы копируются по значению: const b = a — создаёт копию. Объекты передаются по ссылке: const b = a — обе переменные указывают на тот же объект. Spread {...obj} создаёт поверхностную копию. structuredClone(obj) — глубокую.
Подробно
Примитивы vs Объекты:
Примитивы (number, string, boolean, null, undefined): const a = 5; const b = a; // b = 5 (копия) b = 10; console.log(a); // 5 (а не изменилась)
Объекты (objects, arrays, functions): const obj1 = { x: 1 }; const obj2 = obj1; // obj2 = ссылка на тот же объект obj2.x = 2; console.log(obj1.x); // 2 (изменился и obj1!)
Почему так? Объект живёт в памяти. Переменная obj1 — это «указатель» на этот объект. const obj2 = obj1 копирует указатель, а не сам объект.
Shallow copy (поверхностная): const original = { a: 1, b: { c: 2 } }; const copy = { ...original };
copy.a = 100; console.log(original.a); // 1 (не изменился)
copy.b.c = 200; console.log(original.b.c); // 200 (изменился!)
Spread копирует только верхний уровень. Вложенные объекты — ссылки.
Deep copy (глубокая): const deepCopy = structuredClone(original); // structuredClone рекурсивно копирует все уровни
Другие способы:
- JSON.parse(JSON.stringify(obj)) — ограничения: теряет undefined, функции, Date
- structuredClone() — современный, поддерживает Date, Map, Set
- Лучше structuredClone для большинства случаев
Ментальная модель
Shallow copy — как сфотографировать дом. Вы видите фотографию (копию), но мебель внутри — та же самая (ссылки на те же объекты). Deep copy — как построить точную Replica дома со всей мебелью.
Примеры
**Самый простой:**
const a = 5;
const b = a;
b = 10;
console.log(a); // 5 (примитив — копия)
const obj1 = { x: 1 };
const obj2 = obj1;
obj2.x = 2;
console.log(obj1.x); // 2 (объект — ссылка)Примитивы копируются по значению. Объекты — по ссылке.
**Простой:**
const original = { name: 'Анна', scores: [90, 85] };
const shallow = { ...original };
const deep = structuredClone(original);
shallow.name = 'Пётр';
console.log(original.name); // 'Анна' (не изменился)
shallow.scores.push(95);
console.log(original.scores); // [90, 85, 95] (изменился!)
deep.scores.push(80);
console.log(original.scores); // [90, 85, 95] (не изменился!)Spread — поверхностная копия (shallow copy). structuredClone — глубокая копия (deep copy).
**Реальный пример:**
function mergeDefaults(user, defaults) {
// structuredClone чтобы не мутировать defaults
const result = structuredClone(defaults);
return { ...result, ...user };
}
const defaults = { theme: 'dark', lang: 'ru', notifications: true };
const userPrefs = { theme: 'light' };
const settings = mergeDefaults(userPrefs, defaults);
console.log(settings);
// { theme: 'light', lang: 'ru', notifications: true }
console.log(defaults.theme); // 'dark' (не мутирован!)Merge с глубоким клонированием предотвращает мутиацию оригиналов.
Частые ошибки
**Неправильно:** Думать, что spread создаёт глубокую копию
**Почему:** Spread {...obj} копирует только верхний уровень. Вложенные объекты — ссылки.
**Правильно:** Для глубокой копии: structuredClone(obj).
**Неправильно:** Использовать JSON.parse(JSON.stringify()) для копирования
**Почему:** Теряет undefined, функции, Date, Map, Set, циклические ссылки.
**Правильно:** Используйте structuredClone() — он поддерживает больше типов.
**Неправильно:** Путать копирование и клонирование массивов
**Почему:** [...arr] — поверхностная копия (shallow copy). structuredClone(arr) — глубокая копия (deep copy).
**Правильно:** Для простых массивов [...arr] достаточно. Для вложенных — structuredClone.
Важно запомнить
- Примитивы — копируются по значению
- Объекты — передаются по ссылке
- Spread {...obj} — shallow copy
- structuredClone(obj) — deep copy
- JSON.parse(JSON.stringify()) — есть ограничения
Связь
Назад: Вы знаете объекты (J11) — теперь вы понимаете, как их копировать.
Вперёд: Следующий урок (JI4) — методы объекта и ключевое слово this.