structuredClone()是浏览器原生深拷贝API,支持Map、Set、Date、RegExp、ArrayBuffer等复杂类型及循环引用,不支持函数、Promise等;Chrome 98+、Firefox 94+、Safari 15.4+原生支持,旧环境可降级为JSON方案或polyfill。

structuredClone() 是浏览器原生支持的深拷贝 API,能安全、高效地在 Extension 各层级(content script、background/service worker、popup、options 页面等)间传递复杂原始数据(如 Map、Set、Date、RegExp、ArrayBuffer、TypedArray、Error 等),避免 JSON 序列化丢失类型或循环引用报错。
为什么 extension 中需要 structuredClone()
Extension 各模块运行在隔离上下文,通信依赖 chrome.runtime.sendMessage、postMessage 或 chrome.tabs.sendMessage。这些通道底层会自动对消息体做结构化克隆(structured clone algorithm),但若手动序列化(如 JSON.stringify)再解析,会导致:
- Date 变成字符串,RegExp 变成空对象,Map/Set 变成普通对象
- ArrayBuffer 视图(如 Uint8Array)丢失关联缓冲区,无法正确读取二进制数据
- 循环引用直接抛错:
TypeError: Converting circular structure to JSON - 函数、undefined、Symbol、Promise 等被静默丢弃(structuredClone 也丢弃它们,但至少不崩溃)
各层级间直接使用 structuredClone() 的典型场景
structuredClone() 本身不用于跨上下文传输,而是用于**在发送前/接收后对数据预处理或还原**,确保你传的是“可克隆结构”,且接收方拿到的是预期类型的数据副本。
-
content script → background:向 background 发送含 ArrayBuffer 的图像处理结果时,先用
structuredClone(data)确保副本独立,再chrome.runtime.sendMessage(data)—— 实际传输仍走克隆算法,但显式调用可提前捕获不可克隆项 -
background → content script:background 收到请求后,从缓存中取出一个带 Date 和 Map 的配置对象,用
structuredClone(config)拷贝一份再发回,避免 content script 修改影响 background 状态 -
popup 页面 ↔ background:popup 表单提交一个含 File 对象的 FormData?不行——File 不可克隆。但可先读取为 ArrayBuffer:
const arrayBuffer = await file.arrayBuffer();,再structuredClone({ name: file.name, data: arrayBuffer })发送
兼容性与降级方案
structuredClone() 在 Chrome 98+、Firefox 94+、Safari 15.4+ 原生支持。旧版浏览器或需兼容:
- 检查是否存在:
if (typeof structuredClone === 'function') { ... } - 降级用
JSON.parse(JSON.stringify(obj))仅适用于纯 JSON 数据(无 Date/RegExp/二进制等) - 更健壮的降级可引入轻量库如 deep-copy(支持 ArrayBuffer、Map、Set),但注意它不处理循环引用,且比原生慢
- 对必须保留类型的场景(如加密密钥、图像像素),应始终使用 ArrayBuffer + TypedArray 组合,它们是 structured clone 算法原生支持的核心类型
注意事项与避坑点
-
不能克隆函数、window、DOM 节点、Promise、Error 实例(虽然 Error 有构造器,但克隆后是普通对象) —— 若需传错误信息,提取
err.message、err.stack、err.name手动构造 Plain Object -
Transferable 对象(如 ArrayBuffer)在 structuredClone 中默认不转移所有权;如需零拷贝传输(尤其大文件),应改用
postMessage(data, [arrayBuffer])显式 transfer,此时原 ArrayBuffer 在发送方变为 detached - service worker 中的 structuredClone() 行为与普通脚本一致,但注意 SW 可能被终止,长期缓存建议用 Cache API 或 IndexedDB,而非内存对象
- content script 注入时机影响可用性:确保 DOM 加载完成后再调用,避免因执行过早导致 API 未就绪(实际极少发生,因现代 Chromium 启动即支持)


















