您如何决定使用哪种类型化数组?

How do you decide which typed array to use?

我正在尝试创建 ArrayBuffer 对象的视图以便对其进行 JSON 化。

var data = { data: new Uint8Array(arrayBuffer) }
var json = JSON.stringify(data)

似乎 ArrayBuffer 的大小与最小的 Uint8Array 无关。到目前为止我没有得到任何 RangeError :) 如果是这样,我如何决定使用哪个类型化数组?

您根据存储在缓冲区中的数据来决定,或者更好地说,根据您对该数据的解释来决定。

此外,Uint8Array 不是一个 8 位数组,它是一个无符号 8 位整数数组。它可以有任何长度。从与 Uint16Array 相同的 ArrayBuffer 创建的 Uint8Array 将是两倍长,因为 ArrayBuffer 中的每个字节都将是 "placed" Uint8Array 的一个元素,而 Uint16Array 每对字节将 "become" 数组中的一个元素。

一个很好的解释是如果我们尝试用二进制来思考会发生什么。尝试 运行 这个:

var buffer = new ArrayBuffer(2);
var uint8View = new Uint8Array(buffer);
var uint16View = new Uint16Array(buffer);

uint8View[0] = 2;
uint8View[1] = 1;

console.log(uint8View[0].toString(2));
console.log(uint8View[1].toString(2));
console.log(uint16View[0].toString(2));

输出将是

10
1
100000010

因为显示为二进制的无符号 8 位整数,所以 2 是 00000010,1 是 00000001。(toString 去除前导零)。

Uint8Array表示一个字节数组。正如我所说,一个元素是一个无符号的 8 位整数。我们只是向它推送了两个字节。

在内存中,这两个字节并排存储为 00000001 00000010(再次使用二进制形式使事情更清楚)。

现在,当您在同一个缓冲区上初始化 Uint16Array 时,它将包含相同的字节,但是因为元素是无符号的 16 位整数(两个字节),所以当您访问 uint16View[0]它将占用前 两个 字节并将它们返回给您。所以 0000000100000010,即没有前导零的 100000010

如果您将此数据解释为以 10 为基数(十进制)的整数,您就会知道它是 0000000100000010 以 10 为基数 (258)。

Uint8ArrayUint16Array 本身都不存储任何数据。它们只是访问 ArrayBuffer.

中字节的不同方式

如何选择使用哪一个?它不是基于偏好,而是基于基础数据。 ArrayBuffer 当您从某些外部源(可能是网络套接字)接收到一些二进制数据并且已经 知道 数据代表什么时,将使用它。它可能是一个无符号 8 位整数列表,或者一个有符号 16 位整数列表,或者甚至是一个混合列表,其中您知道第一个元素是 8 位整数而下一个元素是 16 位整数。然后您可以使用 DataView 从中读取键入的项目。 如果您不知道数据代表什么,您就无法选择使用什么。