


structuredClone() создаёт глубокую копию поддерживаемых значений JavaScript, включая вложенные объекты и циклические ссылки. Но это не универсальное копирование любого объекта приложения. На Mentoring.digital покажем, где оно полезнее поверхностного копирования и где нужно другое решение.
Выражение {...original} создаёт новый внешний объект, но вложенный массив остаётся той же ссылкой. Если требуется независимый снимок данных формы или конфигурации, изменение вложенного элемента через такую копию может затронуть оригинал.
Сначала решите, действительно ли нужна полная копия. Для изменения одного поля состояния часто достаточно явно скопировать нужную ветку. Для передачи данных по сети нужен формат сериализации; копия объекта в памяти сама по себе не является JSON.
const original = {
items: [{done: false}],
created: new Date('2026-01-01T00:00:00Z'),
counts: new Map([['ready', 2]])
};
original.self = original;
const copy = structuredClone(original);
copy.items[0].done = true;
console.log(original.items[0].done); // false
console.log(copy.created instanceof Date); // true
console.log(copy.counts.get('ready')); // 2
console.log(copy.self === copy); // true
Новый массив и его элементы не совпадают по ссылке с исходными. Цикл не разрывается: поле self в копии указывает на саму копию. Для этого не нужен промежуточный текстовый JSON.
Конструкция JSON.parse(JSON.stringify(value)) имеет другую семантику: например, дата превращается в строку, а цикл приводит к ошибке. Поэтому выбор между этими подходами должен учитывать типы данных, а не только внешне похожий результат для простого объекта.
try {
structuredClone({run() {}});
} catch (error) {
console.log(error.name); // DataCloneError
}
Функция внутри значения не может быть скопирована этим алгоритмом. Сначала отделите данные от поведения: передавайте идентификаторы и параметры, а нужную функцию выбирайте в принимающем коде. Не заменяйте неподдерживаемые поля молча, если это меняет смысл объекта.
У экземпляров пользовательских классов не следует ожидать сохранения цепочки прототипов и методов как у исходного экземпляра. Для объекта с инвариантами может понадобиться явная фабрика или конструктор, который восстановит допустимое состояние из данных.
const buffer = new ArrayBuffer(8);
const moved = structuredClone(buffer, {
transfer: [buffer]
});
console.log(buffer.byteLength); // 0
console.log(moved.byteLength); // 8
После передачи исходный буфер отсоединён. Это принципиально отличается от обычной независимой копии. Применяйте transfer только там, где вызывающий код больше не должен использовать переданный ресурс.
Перед заменой существующего копирования проверьте три случая: вложенное изменение не затрагивает оригинал, нужные типы сохраняются, неподдерживаемые значения дают ожидаемую ошибку. Если задача связана с состоянием интерфейса, можно обсудить подход с наставником по JavaScript. Примеры проверены локально в Node.js; поддержку API в целевых браузерах нужно учитывать отдельно.