结构化克隆是postmessage自动触发的深拷贝机制,支持基本类型、object、array、map、set、date、regexp、arraybuffer等,不支持function、error、dom节点等;它通过无共享内存、类型保真、无副作用保障安全,但大对象传输有性能开销,可使用transferable objects优化。

结构化克隆(Structured Clone)是浏览器自动启用的默认机制,用于在主线程与 Web Worker 之间安全传递数据。它不是手动调用的 API,而是在你调用 postMessage() 时底层自动触发的深拷贝过程。关键在于“理解它怎么工作”和“知道什么时候该让它工作、什么时候该绕开它”。
哪些数据能被安全克隆?
现代浏览器(Chrome 98+、Firefox 94+、Safari 15.4+)支持以下类型,传输后保持原语义和类型:
- 基本类型:
null、undefined、boolean、number、string、bigint - 对象与集合:普通
Object、Array、Map、Set、Date、RegExp - 二进制与媒体:(
ArrayBuffer、TypedArray、Blob、File、ImageData、ImageBitmap)
⚠️ 不支持的会直接抛出 DataCloneError,比如:function、Error、Promsie、DOM 节点、window、document、console。
为什么说它“安全”?
安全来自三重隔离设计:
- 无共享内存:克隆生成的是全新副本,主线程改对象,Worker 里完全不受影响
-
类型保真:
new Date()过去还是Date实例,不是字符串;new Map()还是Map,不是普通对象 -
无副作用:不执行 getter/setter、不调用
toJSON()、不触发任何用户代码,纯数据搬运
如何避免克隆带来的性能陷阱?
克隆虽安全,但对大对象(>几 MB)会产生明显 CPU 和内存开销。这时要主动干预:
- 传大数组或图像像素时,优先用
Transferable Objects:把ArrayBuffer“转移”过去(而非复制),语法为worker.postMessage(buffer, [buffer]);转移后主线程不能再访问该 buffer - 避免传整个含大量嵌套对象的配置项,只传真正需要的字段,或提前序列化为紧凑结构(如扁平 key-value 对象)
- 对频繁通信的小消息(如状态更新),可封装成轻量对象,避开 Map/Set 等高开销类型
兼容性与降级建议
老版本浏览器(如 IE 或旧 Android WebView)不支持结构化克隆,postMessage 会退化为 JSON 序列化:
- 此时
Date变字符串、Map变空对象、undefined消失、循环引用直接报错 - 若需兼容,可在发送前用
canTransfer检测(非标准,仅作参考),或统一走JSON.stringify/parse+ 类型重建逻辑 - 生产环境建议通过
if (typeof structuredClone === 'function')判断是否可用原生克隆能力











