structuredClone & Transferables
structuredClone() (глобальная функция с Node.js 17+, браузеры 2022) — нативный deep clone с поддержкой циклических ссылок, Map/Set/Date/RegExp/ArrayBuffer, но без функций и prototype chain; Transferables обеспечивают zero-copy передачу в Worker.
// structuredClone: поддерживаемые типыconst original = { date: new Date(), map: new Map([['key', 'value']]), set: new Set([1, 2, 3]), regex: /test/gi, buffer: new ArrayBuffer(8), typed: new Uint8Array([1, 2, 3]), error: new Error('msg'), // Node 17.3+ / Chrome 98+ nested: { arr: [1, 2, 3] },};original.circular = original; // циклическая ссылка!
const clone = structuredClone(original);clone.nested.arr.push(4);console.log(original.nested.arr.length); // 3 — настоящий deep cloneconsole.log(clone.circular === clone); // true — цикл сохранёнconsole.log(clone.date === original.date); // false — тоже клонирован// Что structuredClone НЕ поддерживает:const bad = { fn: () => {}, // функции sym: Symbol('x'), // Symbol values dom: document.querySelector('div'), // DOM nodes wm: new WeakMap(), // WeakMap/WeakSet/WeakRef};
try { structuredClone(bad);} catch (e) { console.log(e.name); // DataCloneError}
// Prototype chain ТЕРЯЕТСЯ:class MyPoint { constructor(x,y) { this.x=x; this.y=y; } add(p) {…} }const p = new MyPoint(1, 2);const c = structuredClone(p);console.log(c instanceof MyPoint); // false — plain object!console.log(typeof c.add); // 'undefined' — методы пропали!
// Для клонирования instances: кастомный serializer или// Object.assign(Object.create(Object.getPrototypeOf(p)), structuredClone(p))// Transferable objects: zero-copy transfer (смена ownership)const buffer = new ArrayBuffer(1024 * 1024); // 1 MBconst view = new Uint8Array(buffer);view.fill(42);
// postMessage с transfer: buffer передаётся в worker без копированияconst worker = new Worker('./worker.js');worker.postMessage({ data: buffer }, [buffer]); // transfer!
// ПОСЛЕ transfer: buffer detached — память принадлежит workerconsole.log(buffer.byteLength); // 0! Попытка чтения → TypeError
// В worker.js:// self.onmessage = ({ data: { data } }) => {// const arr = new Uint8Array(data); // arr.length = 1048576// self.postMessage({ result: data }, [data]); // вернуть обратно// };
// Transferable типы: ArrayBuffer, MessagePort, ImageBitmap,// OffscreenCanvas, ReadableStream, WritableStream, TransformStream// structuredClone с transfer:const clone = structuredClone(buffer, { transfer: [buffer] });Итог: structuredClone — правильный нативный deep clone для сложных объектов с циклами и типизированными массивами; Transferables обеспечивают zero-copy передачу бинарных данных между Workers через смену ownership.