结构化克隆是主线程与Web Worker间默认的数据传输机制,属于深拷贝而非浅拷贝,支持循环引用和特定内置类型,但跳过函数、undefined等不可序列化值;ArrayBuffer等需通过transfer实现零拷贝。

主线程和 Web Worker 之间的数据传输默认是结构化克隆(structured clone),本质上属于深拷贝,但不是传统意义上的递归深拷贝——它有明确的类型支持范围和限制。
结构化克隆的特点
结构化克隆是浏览器内置的序列化机制,用于在不同 JavaScript 执行上下文(如主线程 ↔ Worker)间安全传递数据。它:
- 递归遍历对象/数组,复制所有可序列化的属性层级
- 自动跳过不可克隆的值:函数、undefined、Symbol、DOM 节点、Promise、Error 实例等
- 能正确处理 Date、RegExp、Map、Set、TypedArray、ArrayBuffer(仅拷贝内容,不转移)等内置类型
- 支持循环引用,不会爆栈(与手写递归深拷贝不同)
- 不保留原型链或 getter/setter,拷贝后对象的 constructor 可能变为 Object
为什么不是“浅拷贝”
浅拷贝只复制第一层属性引用,而结构化克隆会深入嵌套结构。例如:
const data = { a: 1, b: { c: 2 } };
worker.postMessage(data); // Worker 收到的是完全独立的对象
// 修改 worker 中的 data.b.c,不会影响主线程 original.data.b.c
这说明嵌套对象也被复制了,不符合浅拷贝定义。
零拷贝是例外,需显式启用
结构化克隆默认对 ArrayBuffer 等二进制数据仍做深拷贝(内存复制),性能差。要实现真正零拷贝,必须使用 Transferable Objects:
- 只支持特定类型:ArrayBuffer、MessagePort、ImageBitmap、OffscreenCanvas 等
- 需在 postMessage 第二个参数中显式传入 transfer list:
worker.postMessage(buffer, [buffer]) - 传输后原 ArrayBuffer 立即失效(
byteLength === 0),Worker 获得独占所有权
实际开发中的选择建议
根据数据特征选方式:
- 小对象、配置项、简单状态 → 直接用
postMessage(obj),依赖结构化克隆即可 - 大块二进制数据(图像、音频、加密缓冲区)→ 必须用
transfer实现零拷贝 - 需共享实时状态且支持现代浏览器 → 可考虑
SharedArrayBuffer + Atomics(注意跨域和 Spectre 缓解策略) - 兼容旧环境且需完整深拷贝 → 用
structuredClone()(比 JSON 方案健壮,支持循环引用)或 fast-copy 库


















