直接用 postmessage() 即可,浏览器已自动启用结构化克隆机制;支持 null、布尔、数字、字符串、bigint、object、array、map、set、date、regexp、arraybuffer、typedarray、blob、file、imagedata 及循环引用,不支持函数、promise、dom 元素等。

直接用 postMessage() 就行,不需要手动调用 structuredClone() —— 浏览器已在底层自动启用结构化克隆机制,只要对象可克隆,传输就是安全、独立、无感的。
哪些对象能安全传递
结构化克隆支持的类型,传过去后仍保持原类型和行为:
- 基础值:null、布尔、数字、字符串、BigInt(需现代环境)
- 容器类:Object、Array、Map、Set(克隆后仍是 Map/Set 实例,不是空对象)
- 时间与正则:Date(仍是 Date 对象)、RegExp(保留 flags 和 test 方法)
- 二进制与文件:ArrayBuffer、TypedArray、Blob、File、ImageData
- 特殊结构:循环引用对象(自动识别并重建,不报错)
不支持的会直接抛 DataCloneError,比如函数、Promise、DOM 元素、WeakMap、Symbol 键(会被忽略)、undefined 属性(部分旧版处理不一致)。
为什么不用手动 structuredClone 再 postMessage
现代浏览器(Chrome 98+、Firefox 94+、Safari 15.4+)调用 postMessage(data) 时,底层已使用结构化克隆算法序列化数据。显式写 worker.postMessage(structuredClone(obj)) 是冗余操作,既不提升安全性,也不改善性能,反而多一次同步深拷贝开销。
正确做法是:
- 主线程直接
worker.postMessage(state) - Worker 中收到的
event.data就是全新副本,与主线程原始对象完全隔离 - 无需在 Worker 里再调用
structuredClone(event.data)
大对象传输优化:用 transfer 零拷贝
当传递 ArrayBuffer 或 TypedArray(如视频帧、音频缓冲)时,默认克隆会复制整块内存,造成性能瓶颈。这时应启用 transfer 机制,把内存“移交”而非“复制”:
- 主线程中:
worker.postMessage({ data, buffer }, [buffer]) - buffer 传入 transfer 列表后,主线程原 buffer 立即 detach(
buffer.byteLength === 0) - Worker 收到的是同一块内存的引用,零拷贝、无额外内存占用
- 注意:transfer 只支持 ArrayBuffer、MessagePort、ImageBitmap 等少数类型
兼容性与降级策略
若需支持旧浏览器或不确定运行环境:
- 检测 API:
typeof structuredClone === 'function' - 安全封装示例:
try { return structuredClone(obj); }
catch { return JSON.parse(JSON.stringify(obj)); }
};
注意:JSON 方案仅适用于纯数据对象,会丢失 Date、Map、RegExp 等类型语义,不可用于需要类型保真的场景。











