structuredClone 能安全完整处理含 ArrayBuffer 的对象:默认复制时创建内存隔离的新副本,数据一致且原 buffer 不变;显式 transfer 时移交所有权实现零拷贝,需传入原始 ArrayBuffer 实例。

structuredClone 能安全、完整地处理含 ArrayBuffer 的对象,既支持默认复制,也支持显式转移,但行为取决于是否传入 transfer 选项。
默认复制:内存独立,数据一致
不带 transfer 时,structuredClone 会为 ArrayBuffer 创建全新副本:
- 新 ArrayBuffer 与原 buffer 内存隔离,
cloned.buffer !== original.buffer - 内容逐字节相同,
new Uint8Array(cloned.buffer).every(...)返回 true - 原始 buffer 不受影响,仍可正常读写
- 若对象中包含 TypedArray(如
new Float32Array(buffer)),其视图类型、偏移、长度均被准确重建,且绑定的是新 buffer
显式 transfer:移交所有权,实现零拷贝
当传入 { transfer: [arrayBuffer] } 时,原 ArrayBuffer 立即被分离(detached):
- 必须传入原始 ArrayBuffer 实例,不能传
typedArray.buffer的别名(尽管值相同,部分环境会拒绝) - 执行后
originalBuffer.byteLength === 0,所有基于它的 TypedArray 或 DataView 失效 - 克隆结果中对应视图的
.buffer指向同一物理内存,但归属已切换——这是真正的 O(1) 迁移 - 适用于大体积数据(如视频帧、音频缓冲区),避免内存复制开销
配合 TypedArray 使用的关键细节
ArrayBuffer 很少单独存在,通常与 TypedArray 配合使用。structuredClone 对此有明确行为:
- 直接克隆 TypedArray(如
structuredClone(new Uint8Array(buf)))时,会自动提取并克隆其底层 buffer - 若需 transfer,仍须在
transfer数组中显式列出该 buffer 实例,而非 TypedArray 本身 - 克隆后的 TypedArray 类型不变(
cloned instanceof Uint8Array为 true),且数据完全一致 - 嵌套结构中(如
{ pixels: new Uint8ClampedArray(...) }),buffer 和视图语义均被保留
常见错误与规避方式
几个高频出错点需特别注意:
- 把 TypedArray 传进 transfer 列表 → 报
DataCloneError;只接受 ArrayBuffer、MessagePort、ImageBitmap 等可转移对象 - 误以为 clone 后 buffer 默认共享 → 实际默认是复制;要共享必须手动复用 buffer,不可依赖 clone 行为
- 在不支持环境(如旧版 Safari)中直接调用 → 先检测
typeof structuredClone === 'function',再降级(如用postMessagepolyfill) - 对象中混入函数、undefined 或 DOM 节点 → 即使其他字段正常,也会整体抛
DataCloneError

















