JavaScript 中主线程通过 postMessage() 向 Web Worker 传递数据采用结构化克隆,仅支持可序列化类型(如字符串、对象、ArrayBuffer 等),不支持函数、DOM 节点等;传输 ArrayBuffer 需通过 transferList 实现零拷贝。

在 JavaScript 中,主线程通过 postMessage() 向 Web Worker 子线程传递数据,本质是**结构化克隆(structured clone)**,不是传引用,也不支持函数、DOM 节点等不可序列化对象。
传递的数据类型要合法
只能传递可被结构化克隆算法处理的值,包括:
- 基本类型:字符串、数字、布尔值、null、undefined(注意:
undefined在某些浏览器中会被忽略或转为null) - 数组、普通对象(不含循环引用)、Date、RegExp、Map、Set、Blob、File、ArrayBuffer、TypedArray、DataView
- 嵌套结构也支持,比如
{ user: { id: 1, name: "Alice" }, tags: ["a", "b"] }
❌ 不支持:function、Promise、Element、window、console、带循环引用的对象、Error 实例等。
传递方式:调用 worker.postMessage()
创建 Worker 后,直接在其实例上调用 postMessage(),第一个参数是要发送的数据,第二个参数(可选)用于传输 ArrayBuffer 或 TypedArray 的所有权(即“转移”而非拷贝,提升性能):
const worker = new Worker('worker.js');
<p>// 普通数据(拷贝)
worker.postMessage({ type: 'FETCH', url: '/api/data' });</p><p>// 传输 ArrayBuffer(零拷贝,原主线程无法再访问该 buffer)
const buffer = new ArrayBuffer(1024);
worker.postMessage({ data: buffer }, [buffer]);
</p>
⚠️ 注意:[buffer] 必须是实际要转移的 ArrayBuffer(或其视图),且不能出现在消息对象内部——必须作为第二个参数显式列出。
子线程接收数据
Worker 内部通过监听 message 事件获取数据,event.data 就是主线程发来的克隆副本:
// worker.js
self.onmessage = function(event) {
const data = event.data; // 已是独立副本,修改不影响主线程
console.log('收到:', data);
<p>// 可以回传结果
self.postMessage({ status: 'done', result: data.value * 2 });
};
</p>
常见易错点
- 误传 this 或闭包变量:Worker 是独立上下文,没有访问主线程作用域的能力
-
忽略 transferList 导致内存未释放:若传了
[buffer]却没在主线程及时丢弃引用,可能延迟 GC -
期望收到函数并执行:函数无法克隆,会静默丢失;需改用字符串 +
eval(不推荐)或预定义逻辑分支 -
跨域 Worker 脚本被阻止:Worker 脚本必须同源,否则抛
SecurityError
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











