跨窗口传递复杂对象时无需手动深拷贝,因postMessage等机制默认使用结构化克隆算法自动完成安全深拷贝;仅当需预处理数据、兼容旧环境或非标准赋值时才需手动深拷贝。

多窗口间传递复杂对象时,深拷贝不是关键问题,关键是“能否传过去”——JavaScript 的 跨窗口通信本身依赖结构化克隆算法,而这个过程天然就是一次安全、自动的深拷贝。
structuredClone 是跨窗口传递的默认机制
当你使用 window.postMessage()、SharedWorker 或 MessageChannel 向另一个窗口发送对象时,浏览器底层调用的就是结构化克隆(Structured Clone Algorithm)。它能正确处理:
- Date、RegExp、Map、Set、ArrayBuffer、TypedArray、Error(部分环境)
- 嵌套对象和数组(递归复制)
- 循环引用(不会报错)
你不需要手动深拷贝再 post;直接传原对象即可。目标窗口收到的,就是一个完全独立、内存隔离的新副本。
哪些值无法跨窗口传递?
结构化克隆有明确限制,以下类型会被静默丢弃或抛出 DataCloneError:
立即学习“Java免费学习笔记(深入)”;
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 函数(
function)、undefined、Symbol - DOM 节点、
Window对象、document - 带有原型方法的自定义类实例(仅保留数据属性,丢失方法和 constructor)
-
Promise、WeakMap、WeakSet
例如:postMessage({ fn: () => {}, date: new Date() }) 中的 fn 会消失,date 会正常保留为 Date 实例。
需要手动深拷贝的少数场景
只有在以下情况才需主动深拷贝:
- 你想在发送前预处理数据(比如剔除敏感字段、转换日期格式)
- 你用的是老式兼容方案(如 IE 不支持 structuredClone,只能退到 JSON 方案)
- 你在主进程与 iframe 之间用
iframe.contentWindow直接赋值(不推荐,应统一走 postMessage)
此时优先选 structuredClone(obj)(现代环境),兼容旧环境可用 lodash.cloneDeep,避免用 JSON.parse(JSON.stringify()) —— 它会把 Date 变字符串、丢掉 Map/Set,导致跨窗口后数据失真。
实际建议:按流程做,别绕弯
标准跨窗口数据传递三步走:
- 确保要传的对象只含可克隆类型(避开 function/undefined/Symbol/原型方法)
- 直接
targetWindow.postMessage(data, origin) - 在接收端监听
message事件,使用event.data—— 它已是安全副本,无需再 clone
强行在发送前加一层深拷贝,既无必要,还可能引入类型误判或性能开销。

















