TypedArray 是直接操作二进制内存的接口,其高性能源于与 ArrayBuffer 的绑定,实现内存连续、零拷贝和类型明确;应避免深拷贝,善用 subarray、transferable 和预分配复用。

TypedArray 不是“更快的数组”,而是直接操作二进制内存的接口。真正带来高性能的关键,在于它与 ArrayBuffer 的绑定关系,以及由此实现的内存连续性、零拷贝访问和类型语义明确性。
用 ArrayBuffer + TypedArray 构建紧凑二进制管道
普通 JavaScript 数组每个元素都是独立对象,带类型标签和 GC 开销;而 Uint8Array 等视图背后共享同一块 ArrayBuffer,数据以纯字节流形式连续存放,读写不触发装箱/拆箱。
- 从网络获取原始二进制:用 fetch().then(res => res.arrayBuffer()) 直接拿到只读 ArrayBuffer,再创建视图,跳过 base64 或字符串中转
- 处理文件:FileReader.readAsArrayBuffer() 返回 ArrayBuffer,配合 new Uint8Array(buffer) 即可开始解析,无需中间转换
- 图像像素:Canvas 的 getImageData().data 是 Uint8ClampedArray,可直接做灰度、对比度等批量运算,像素字节零复制对接
切片复用:用 subarray() 和偏移构造实现零拷贝分段
TypedArray 的 subarray(start, end) 返回新视图,不复制底层数据,只是改变起始偏移和长度——这是零拷贝的核心操作。
- 协议解析时,按字段长度切片:new Uint32Array(buffer, 0, 1)[0] 读头部长度,再 new Uint8Array(buffer, 4, len) 取有效载荷
- 音频处理中,Float32Array 视图用于 FFT 运算,Uint16Array 视图用于导出 WAV 头部,共用同一 buffer
- 避免使用 Uint8Array.from([...]) 或传入普通数组构造,这会强制深拷贝,彻底丢失优势
跨上下文高效传递:用 transferable 实现内存所有权移交
在主线程与 Web Worker 之间传递大块二进制数据时,复制成本极高。正确做法是把 ArrayBuffer 本身转移过去。
- 发送端:worker.postMessage(buffer, [buffer]) —— 第二个参数声明 transfer list,buffer 将被移除引用,原线程无法再访问
- 接收端 worker 中直接使用:const view = new Uint8Array(e.data),无拷贝、无延迟
- 注意:只能 transfer ArrayBuffer,不能 transfer TypedArray 实例;transfer 后原视图变为 detached,需检查 view.buffer.byteLength 防异常
预分配 + 视图复用:应对超大规模数据(如点云、视频帧)
反复 new ArrayBuffer 容易引发 V8 内存抖动甚至 OOM。对 GB 级数据,应预分配大块内存,按需映射视图。
- 初始化:const ab = new ArrayBuffer(2 * 1024 * 1024 * 1024); // 2GB 预分配
- 每次处理新片段:new Float64Array(ab, offset, count),复用同一 buffer
- 注意字节对齐:Int32Array 要求 offset % 4 === 0,否则可能静默失败或读错数据
- ArrayBuffer 无法局部释放,仅当所有视图都无引用后由 GC 回收










