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

Какую ошибку можно получить при мутации вложенного объекта, скопированного через Object.assign?

1.8 Middle🔥 111 комментариев
#JavaScript Core

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

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

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

Глубокая vs. Поверхностная копия: Ошибки при мутации

Основная ошибка, которую можно получить при мутации вложенного объекта, скопированного через Object.assign(), связана с тем, что этот метод создает только поверхностную (shallow) копию. Это приводит к неожиданному совместному использованию ссылок на вложенные объекты между оригиналом и копией.

Конкретная ошибка: Случайное изменение оригинала

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

const original = {
    name: 'Main',
    data: {
        value: 1,
        items: ['a', 'b']
    }
};

// Создаем копию через Object.assign
const copy = Object.assign({}, original);

// Мутируем вложенный объект в копии
copy.data.value = 999;
copy.data.items.push('c');

console.log(original.data.value); // 999 (!) - Ошибка! Изменился оригинал.
console.log(original.data.items); // ['a', 'b', 'c'] (!) - Тоже изменился.

Механизм ошибки

При выполнении Object.assign({}, original):

  • Примитивные значения (name) копируются по значению.
  • Ссылочные типы (data) копируются по ссылке. В памяти создается новый объект верхнего уровня, но его свойство data указывает на тот же самый объект в памяти, что и original.data.

Последствия и сложности отладки

  1. Нарушение инкапсуляции: Компонент, работающий с "копией", неявно влияет на состояние другого компонента, использующего оригинал.
  2. Сложная отладка: Изменения происходят вдали от места мутации, что может нарушать принцип предсказуемости состояния в приложениях (особенно в связке с React, Vue, Redux).
  3. Трудноуловимые баги: Ошибка может проявиться не сразу, а через цепочку вызовов.

Альтернативы для глубокого копирования

Для безопасной мутации вложенных структур необходима глубокая копия (deep copy):

  1. JSON-метод (с ограничениями):

    const deepCopy = JSON.parse(JSON.stringify(original));
    // Не копирует функции, undefined, Symbol, цикличные ссылки
    
  2. Нативная функция structuredClone() (современный вариант):

    const deepCopy = structuredClone(original);
    // Поддерживает большинство типов, включая Map, Set, Date
    
  3. Ручная рекурсивная функция или использование библиотек:

    // Пример с Lodash
    import { cloneDeep } from 'lodash';
    const deepCopy = cloneDeep(original);
    

Когда Object.assign() уместен

Object.assign() остается полезным для:

  • Создания копий плоских объектов (без вложенности)
  • Слияния конфигураций
  • Иммутабельных обновлений в Redux-редюсерах для верхнего уровня

Практический совет

Всегда анализируйте структуру объекта перед копированием. Если есть вложенные объекты/массивы — используйте глубокое копирование. В современном JavaScript structuredClone() стал стандартным решением для большинства сценариев, где требуется глубокая копия без сторонних зависимостей.