JavaScript中深拷贝ArrayBuffer需手动处理:ArrayBuffer用slice(),类型化数组用new constructor(),DataView需先拷贝buffer;现代推荐structuredClone(),但不支持函数、SharedArrayBuffer等。

JavaScript 中直接使用 JSON.parse(JSON.stringify()) 或结构赋值({...obj}、[...arr])无法拷贝 ArrayBuffer 及其视图(如 Uint8Array、DataView),因为它们是不可序列化的原始二进制数据。要实现包含 ArrayBuffer 的深拷贝,需手动识别并克隆这些对象。
识别并单独处理 ArrayBuffer 和类型化数组
深拷贝逻辑中需检测对象是否为 ArrayBuffer、SharedArrayBuffer、或任意类型化数组(Int8Array、Float64Array 等)、DataView。对这些对象不能递归遍历,而应调用其原生的复制方法:
-
ArrayBuffer→ 使用slice(0)创建新缓冲区并拷贝内容 - 类型化数组(如
Uint8Array)→ 调用slice()或构造新实例:new Uint8Array(original.buffer.slice()) -
DataView→ 需先拷贝底层ArrayBuffer,再用新缓冲区创建新DataView
使用 structuredClone(现代推荐方案)
Chrome 98+、Firefox 94+、Safari 15.4+ 支持 structuredClone(),它原生支持 ArrayBuffer、类型化数组、Map、Set、Date、RegExp 等,且能正确处理循环引用:
const copied = structuredClone(originalObject);
注意:不支持函数、undefined、Symbol、Error 对象,也不支持 SharedArrayBuffer(会抛错)。若目标环境支持,这是最简洁可靠的方案。
立即学习“Java免费学习笔记(深入)”;
手写兼容性深拷贝函数(含 ArrayBuffer 支持)
当需兼容旧浏览器或需要精细控制时,可扩展一个递归拷贝函数,显式处理二进制对象:
- 用
ArrayBuffer.isView(obj)或obj.buffer instanceof ArrayBuffer判断类型化数组 - 用
obj instanceof ArrayBuffer判断缓冲区本身 - 对
ArrayBuffer:返回obj.slice() - 对类型化数组:返回
new obj.constructor(obj)(自动复用缓冲区副本) - 对普通对象/数组:递归拷贝属性,跳过不可枚举或原型链属性(除非明确需要)
示例关键片段:
if (obj instanceof ArrayBuffer) return obj.slice(); if (ArrayBuffer.isView(obj)) return new obj.constructor(obj);
注意 SharedArrayBuffer 和 transferables 的特殊性
SharedArrayBuffer 不可被拷贝(设计上就是共享内存),structuredClone 会直接报错。若业务中用到它,拷贝逻辑应提前检查并抛出明确错误,或转换为普通 ArrayBuffer 后再处理。另外,postMessage 中的 transfer 机制是零拷贝转移,不属于深拷贝范畴,勿混淆。


















