Что такое structuredClone в JavaScript и когда его применять?
Что это такое
structuredClone — глобальная функция, доступная в браузерах и в Node.js начиная с 17-й версии, которая выполняет глубокое клонирование значения. В её основе лежит тот же алгоритм structured clone algorithm, что используется движком при передаче данных через postMessage, запись в IndexedDB и обмен сообщениями с Web Worker'ами. До её появления для глубокого копирования приходилось использовать JSON.parse(JSON.stringify(x)) или библиотеки вроде lodash cloneDeep.
const original = { user: { name: 'Аня' }, tags: [1, 2, 3] };
const clone = structuredClone(original);
clone.user.name = 'Боря';
console.log(original.user.name); // 'Аня' — оригинал не затронут
console.log(original === clone); // false
console.log(original.user === clone.user); // false, вложенные объекты тоже скопированы
Что умеет клонировать
- Обычные объекты и массивы, в том числе вложенные и с циклическими ссылками
Map,Set,Date,RegExpArrayBuffer,TypedArray,DataViewBlob,File,ImageData- Ошибки (
Error) — частично, с потерей некоторых свойств
Чего не умеет
- Функции — попытка клонировать функцию или объект с методом бросает
DataCloneError - DOM-узлы
Symbolи свойства с ключами-символами- Геттеры/сеттеры и дескрипторы свойств — клон получает обычные data-properties
- Прототипная цепочка кастомных классов — экземпляр класса превращается в обычный объект с
Object.prototype
class User {
constructor(name) { this.name = name; }
greet() { return `Привет, ${this.name}`; }
}
const u = new User('Аня');
const clonedUser = structuredClone(u);
console.log(clonedUser instanceof User); // false — прототип потерян
console.log(clonedUser.greet); // undefined — метода нет
Когда применять
- Нужен надёжный глубокий клон данных без подключения lodash
- Работа с Web Worker'ами — данные всё равно проходят через structured clone при
postMessage, поэтому логично использовать тот же механизм явно - Снятие снапшота состояния для undo/redo или сравнения до/после мутации
- Клонирование сложных данных с
Date,Map,Set, которыеJSON.stringifyиспортит
Когда не подходит
- Нужно сохранить методы/прототип класса — тогда лучше писать собственный метод
clone()или использоватьObject.create - Критична производительность на очень больших структурах в горячем пути — стоит измерить и рассмотреть неглубокое копирование через spread, если глубина не нужна
- Нужно клонировать функции как значения (например, конфиг с колбэками)
Сравнение с альтернативами
JSON.parse(JSON.stringify(x)) — теряет undefined, функции и Symbol, превращает Date в строку, не поддерживает циклические ссылки (кидает ошибку) и Map/Set.
structuredClone — быстрее и поддерживает больше встроенных типов, но всё ещё не про кастомные классы и функции.
structuredClone также принимает опцию transfer для передачи владения ArrayBuffer без копирования — актуально при обмене данными с воркерами.
const buffer = new ArrayBuffer(1024);
const clone = structuredClone({ buffer }, { transfer: [buffer] });
// buffer.byteLength теперь 0 — владение передано, а не скопировано
Что хочет услышать интервьюер
Понимание, что это встроенный способ глубокого клонирования, а не поверхностного (shallow)
Знание ограничений: функции, DOM-узлы, Symbol и прототипы классов не клонируются
Умение сравнить с JSON.parse(JSON.stringify()) и объяснить преимущества (Date, Map, Set, циклические ссылки)
Знание связи structuredClone с postMessage/Web Workers/IndexedDB
Понимание опции transfer для ArrayBuffer
Пример: Базовое глубокое клонирование
const original = {
createdAt: new Date(),
tags: new Set(['a', 'b']),
meta: new Map([['k', 1]]),
};
const clone = structuredClone(original);
console.log(clone.createdAt instanceof Date); // true
console.log(clone.tags instanceof Set); // true
console.log(clone === original); // false
Пример: Ошибка при клонировании функции
try {
structuredClone({ fn: () => {} });
} catch (e) {
console.log(e.name); // 'DataCloneError'
}
Пример: Циклические ссылки — не проблема
const a = { name: 'a' };
a.self = a; // циклическая ссылка
const clone = structuredClone(a);
console.log(clone.self === clone); // true, структура сохранена
Типичные ошибки
Утверждают, что structuredClone клонирует функции или методы класса — на самом деле бросается DataCloneError или метод теряется
Путают structuredClone с поверхностным копированием через spread или Object.assign
Не знают, что клон экземпляра класса теряет прототип и становится обычным объектом
Забывают, что это относительно новая функция и может отсутствовать в старых окружениях (нужен полифилл или проверка поддержки)
Считают, что structuredClone эквивалентен JSON.stringify по возможностям, не упоминая поддержку Date, Map, Set, циклических ссылок


