推荐使用纯 json 可序列化对象而非裸对象或字符串:因 postmessage 依赖结构化克隆算法,json 结构能规避函数、dom 节点等不可克隆值风险,且无需手动 stringify/parse,接收端直接校验字段类型即可。

JSON 格式本身不是 postMessage 的强制要求,但它是跨源通信中最常用、最稳妥的数据载体。原因在于:postMessage 底层使用结构化克隆算法(Structured Clone Algorithm)序列化数据,而 JSON 兼容性好、结构清晰、无副作用,能自然适配这一机制,同时规避函数、DOM 节点、undefined、Symbol 等不可克隆值带来的风险。
为什么推荐用 JSON 结构(而非裸对象或字符串)
- postMessage 支持任意可序列化值(Object、Array、Number、String、Boolean、null、Date、RegExp、Blob、File、ArrayBuffer 等),但不同浏览器对复杂类型的支持存在差异;
- 直接传
{"user": {name: "Alice", role: () => {}}}会因含函数而静默失败(不报错,但接收方 data 为{}或undefined); - 传
JSON.stringify(obj)后再JSON.parse(event.data)是冗余且易出错的双序列化,没必要; - 最佳实践是:直接传 plain object(纯 JSON 可序列化对象),不包含不可克隆字段,由 postMessage 自动处理序列化。
发送端:构造符合 JSON 语义的 plain object
-
✅ 推荐写法(安全、简洁、可读性强):
const payload = { type: "login", userId: 123, timestamp: Date.now(), preferences: { theme: "dark", lang: "zh-CN" } }; iframe.contentWindow.postMessage(payload, "https://trusted.com"); -
❌ 避免这些:
- 函数、箭头函数、class 实例、Promise、RegExp(除非明确需要且目标环境支持);
- DOM 元素、window、document、this 等宿主对象;
- undefined 字段(会被忽略,可能造成接收方逻辑误判);
- 循环引用对象(结构化克隆会抛
DataCloneError)。
接收端:不做 JSON.parse,但要做类型与字段校验
-
postMessage 已自动反序列化,
event.data就是原始 JS 对象(不是字符串):window.addEventListener("message", (e) => { if (e.origin !== "https://trusted.com") return; const data = e.data; // 类型检查(防空/非对象) if (!data || typeof data !== "object") return; // 关键字段存在性 & 类型校验(避免 .type 报错) if (typeof data.type !== "string") return; if (data.type === "login" && typeof data.userId !== "number") return; console.log("Valid message:", data); });
补充建议:统一约定消息结构提升健壮性
- 所有消息带
type字段,便于路由分发; - 可选加
id(UUID)和version,支持幂等或协议演进; - 复杂嵌套建议用
JSON.stringify(data, null, 2)临时调试输出,但生产环境不需 stringify; - 如需兼容极老环境(如 IE8–9),才退化为手动
JSON.stringify+JSON.parse,但此时需确保双方都做,且 targetOrigin 不能用"*"。
本质上,JSON 不是 postMessage 的格式约束,而是开发者约定的“最小安全交集”——它天然避开不可序列化陷阱,又保持语义明确,适合跨源场景下的可信协作。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











