ArrayBuffer是什么
预计阅读时间: 5 分钟
"ArrayBuffer
ArrayBuffer 是 JavaScript 中用于存储二进制数据的对象。它是一个固定长度的原始二进制数据缓冲区,不能直接操作其中的数据,需要通过其他对象(如 TypedArray 或 DataView)来访问和操作。
其中有几个关键点:
"ArrayBuffer与Array 的区别
ArrayBuffer 与 Array 没有任何关系:
- 它的长度是固定的,我们无法增加或减少它的长度。
- 它正好占用了内存中的那么多空间。
- 要访问单个字节,需要另一个“视图”对象,而不是
buffer[index]。
ArrayBuffer 的用途
ArrayBuffer 通常用于处理二进制数据,例如:
- 读取和写入文件
- 处理网络协议
- 加密和解密
- 数据传输和存储
如在3D渲染中,ArrayBuffer 可以用于存储顶点数据、法向量、纹理坐标等。gltf格式的模型文件,bin文件就可以使用ArrayBuffer来存储。
ArrayBuffer 的创建
main.js
1let buffer = new ArrayBuffer(16); // 创建一个长度为 16 的 buffer
2alert(buffer.byteLength); // 16
3// 它会分配一个 16 字节的连续内存空间,并用 0 进行预填充。
4// 以字节为单位,每个字节是8位二进制,所以16字节就是128位
TypedArray
TypedArray 是 ArrayBuffer 的视图,它提供了对缓冲区内容的类型化访问。
"TypedArray
视图对象 是操作 ArrayBuffer的工具,本身并不存储任何东西,而是通过它的规则解释存储在 ArrayBuffer中的字节
TypedArray的类型
Uint8Array
将 ArrayBuffer 中的每个字节视为 0 到 255 之间的单个数字(每个字节是 8 位,因此只能容纳那么多)。这称为 【8 位无符号整数】。
Uint16Array
将每 2 个字节视为一个 0 到 65535 之间的整数。这称为 【16 位无符号整数】。
Uint32Array
将每 4 个字节视为一个 0 到 4294967295 之间的整数。这称为 【32 位无符号整数】。
Float64Array
将每 8 个字节视为一个 5.0x10^-324^ 到 1.8x10^308^之间的浮点数。

因此,一个 16 字节 ArrayBuffer 中的二进制数据可以解释为 16 个“小数字”,或 8 个更大的数字(每个数字 2 个字节),或 4 个更大的数字(每个数字 4 个字节),或 2 个高精度的浮点数(每个数字 8 个字节)
TypedArray属性和方法
1. 创建方法
main.js
1// 以上的几种类型数组,都有以下5中函数重载的实现,Uint32Array
2new TypedArray(buffer, [byteOffset], [length]); // 除了提供buffer外,其他情况都会创建新的buffer
3new TypedArray(object);
4new TypedArray(typedArray);
5new TypedArray(length);
6new TypedArray();
2. 属性
arr.buffer —— 引用 ArrayBuffer。
arr.byteLength —— ArrayBuffer 的长度
3. 越界行为
对于越界值,会采用仅保留最右位,多余的位被切除的操作

Uint8ClampedArray 在这方面比较特殊,它的表现不太一样。对于大于 255 的任何数字,它将保存为 255,对于任何负数,它将保存为 0。此行为对于图像处理很有用。
4. 方法
TypedArray 具有常规的 Array 方法,但有个明显的例外。我们可以遍历(iterate),map,slice,find 和 reduce 等。
"TypedArray 的限制
但有几件事我们做不了:
- 没有
splice —— 我们无法“删除”一个值,因为类型化数组是缓冲区(buffer)上的视图,并且缓冲区(buffer)是固定的、连续的内存区域。我们所能做的就是分配一个零值。
- 无
concat 方法。
还有两种其他方法:
main.js
1arr.set(fromArr, [offset])
2 // 从 offset(默认为 0)开始,将 fromArr 中的所有元素复制到 arr。
3 arr.subarray([begin, end])
4 // 创建一个从 begin 到 end(不包括)相同类型的新视图。这类似于 slice 方法(同样也支持),但不复制任何内容 —— 只是创建一个新视图,以对给定片段的数据进行操作。
DataView ——更灵活的TypedArray
DataView 是在 ArrayBuffer 上的一种特殊的超灵活“未类型化”视图。它允许以任何格式访问任何偏移量offset的数据。
"DataView
- 对于类型化的数组,构造器决定了其格式。整个数组应该是统一的。第 i 个数字是 arr[i]。
- 通过
DataView,我们可以使用 .getUint8(i) 或 .getUint16(i) 之类的方法访问数据。我们在调用方法时选择格式,而不是在构造的时候。
main.js
1new DataView(buffer)
2new DataView(buffer, byteOffset)
3new DataView(buffer, byteOffset, byteLength)
4
5// buffer —— 底层的 ArrayBuffer。与类型化数组不同,DataView 不会自行创建缓冲区(buffer)。我们需要事先准备好。
6// byteOffset —— 视图的起始字节位置(默认为 0)。
7// byteLength —— 视图的字节长度(默认至 buffer 的末尾)。
main.js
1// 4 个字节的二进制数组,每个都是最大值 255
2let buffer = new Uint8Array([255, 255, 255, 255]).buffer;
3
4let dataView = new DataView(buffer);
5
6// 在偏移量为 0 处获取 8 位数字
7alert( dataView.getUint8(0) ); // 255
8
9// 现在在偏移量为 0 处获取 16 位数字,它由 2 个字节组成,一起解析为 65535
10alert( dataView.getUint16(0) ); // 65535(最大的 16 位无符号整数)
11
12// 在偏移量为 0 处获取 32 位数字
13alert( dataView.getUint32(0) ); // 4294967295(最大的 32 位无符号整数)
14
15dataView.setUint32(0, 0); // 将 4 个字节的数字设为 0,即将所有字节都设为 0
通过 DataView ,就可以更自由操作二进制数字了