structured clone 与 Transferable
沿用上一节的 worker.js 入口,本节用两个可控对象观察 structured clone 与 Transferable 的身份和所有权变化。
js
const worker = new Worker('worker.js')
const buffer = new ArrayBuffer(8)
worker.postMessage({ buffer }, [buffer])
console.log(buffer.byteLength)Transfer 后主线程的 buffer.byteLength 变为 0;不放入 transfer list 时则复制数据,主线程仍拥有可读缓冲区。
机制拆解
structured clone 会复制可克隆对象;Transferable 会转移所有权。对同一个 ArrayBuffer 分别使用 postMessage({ buffer }) 与 postMessage({ buffer }, [buffer]),前者保持主线程长度,后者让主线程视图变为 detached。不能在转移后继续写入原缓冲区。
边界与失败路径
- 所有权:监听器、observer、worker、连接、缓存和焦点都有创建者与释放时机;页面隐藏、路由离开和元素移除时都要验证。
- 宿主差异:SSR、Web Worker、Shadow DOM、跨文档、跨源和辅助技术不会共享同一套全局对象与事件路径。
- 错误分类:取消、超时、权限拒绝、协议错误、配额不足和浏览器不支持应分别进入可观察状态。
- 安全边界:用户输入、URL、HTML、消息和持久化数据不能仅因为来自同源或类型正确就视为可信。
可运行实验
创建一个 Worker,先发送不带 transfer list 的 ArrayBuffer,再发送带 transfer list 的副本;记录两次发送后主线程 byteLength,并在答案中解释所有权变化。
实验记录要包含运行时、输入步骤、预期输出、实际日志和未覆盖的宿主差异。
练习
- 发送普通对象、含 Date 的对象和 ArrayBuffer,记录 Worker 收到的类型与长度。
- 对同一个缓冲区分别使用复制和 transfer,解释主线程 byteLength 差异。
- 说明何时选择 Transferable,何时复制更安全。 查看本节答案
下一步
完成练习后回到本章概览,按下一篇继续;遇到跨章节故障,先回到本节的所有权与宿主边界。