messagechannel 传输 json 数据时不自动序列化,而是使用结构化克隆算法进行深拷贝,支持 date、regexp、arraybuffer 等类型,但不支持函数、undefined(部分环境)、循环引用和 dom 节点;推荐直接传递原生对象而非手动 json 序列化。

JSON数据在 MessageChannel 中**不会被自动序列化**,而是依赖浏览器底层的**结构化克隆算法(Structured Clone Algorithm)**进行复制。这个过程对符合要求的 JSON-like 数据(如纯对象、数组、字符串、数字、布尔值、null、Date、RegExp、ArrayBuffer 等)是透明且高效的,但它不是“JSON 序列化”(即不调用 JSON.stringify() 或 JSON.parse()),也不支持函数、undefined、循环引用、DOM 节点等。
MessageChannel 传输的是结构化克隆,不是 JSON 字符串
当你通过 port.postMessage(data) 发送一个普通 JS 对象(例如 {name: "Alice", age: 30})时:
- 浏览器内部使用结构化克隆算法复制该对象,生成一份**深拷贝**,并跨线程(如主线程 ↔ Worker)安全传递;
- 该过程不经过字符串化(即不会变成
"{...}"),也不依赖JSON.stringify的规则(比如它能传Date、Uint8Array,而 JSON 不能); - 接收端收到的是一个**新对象**,与原对象内存隔离,修改它不会影响发送端。
哪些数据能被成功传输?
只要数据满足结构化克隆的可复制条件,就能直接传。常见可传类型包括:
- 基本类型:string、number、boolean、null、undefined(⚠️注意:
undefined在部分旧浏览器或某些上下文中可能被忽略或丢弃); - 嵌套对象和数组(纯数据,无函数、无原型方法、无循环引用);
-
Date、RegExp、Map、Set(现代浏览器支持); -
ArrayBuffer、TypedArray、ImageData(可转移或拷贝,取决于是否传入transfer列表)。
❌ 不支持:function、Promise、Symbol、DOM 元素、window、this、含循环引用的对象。
需要手动 JSON 序列化的场景
只有当你明确需要字符串形式(比如日志记录、与后端交互、或兼容老环境),才需手动处理:
- 发送前:
port.postMessage(JSON.stringify(obj)); - 接收后:
JSON.parse(event.data); - 但这样会多一次解析开销,且丢失 Date、RegExp 等类型(变成字符串)。
✅ 推荐做法:直接传原生对象,让结构化克隆处理——更高效、更安全、类型保留更好。
验证是否“自动”生效的小技巧
可以快速测试:
const { port1, port2 } = new MessageChannel();
port2.onmessage = e => {
console.log(e.data instanceof Date); // true(如果发了 new Date())
console.log(e.data.constructor.name); // 如 "Object"、"Array"、"Date"
};
port1.postMessage({ now: new Date(), list: [1,2,3] });
输出会显示类型被完整保留,证明不是 JSON 字符串中转。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











