小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
Typed Array API 中存在两个对象
Buffers
ArrayBuffer 的实例用于持有二进制数据
Views
提供访问二进制数据的方式,主要有两种视图
- Typed Array 的构造函数的实例(Uint8Array、Float64Array等)的工作方式与普通数组很相似,但需要其元素的类型需要一致,并且没有空穴。
- DataView 的一个实例让你在缓冲区的任何字节偏移处访问数据,并将该数据解释为几种类例如(Uint8、Float64等)。
这是一个类型化数组API的结构图
在下表中列出 API 支持的类型
| Element type | Bytes | Description | C type |
|---|---|---|---|
| Int8 | 1 | 8-bit signed integer | signed char |
| Uint8 | 1 | 8-bit unsigned integer | unsigned char |
| Uint8C | 1 | 8-bit unsigned integer (clamped conversion) | unsigned char |
| Int16 | 2 | 16-bit signed integer | short |
| Uint16 | 2 | 16-bit unsigned integer | unsigned short |
| Int32 | 4 | 32-bit signed integer | int |
| Uint32 | 4 | 32-bit unsigned integer | unsigned int |
| Float32 | 4 | 32-bit floating point | float |
| Float64 | 8 | 64-bit floating point | double |
这里要特别说一说 Uint8C 元素类型,这个类型并不被 DataView 所支持支持,只为启用Uint8ClampedArray 而存在。这个类型的数组是为 canvas 专用(目的是取代CanvasPixelArray)。Uint8C 和 Uint8的唯一区别是如何处理overflow 和 underflow,这个会在随后给出解释。建议避免使用前者。
因为 PC 对数字表示具有极限能力,由overflow & underflow现象产生的错误叫做Rounding Error。Rounding Error有时会导致系统奔溃,所以我们必须要采用一些方式来避免这种问题。解决问题的思路就是要通过变形,将极大数极小数变形为普通数。
我想说的是,Uint8ClampedArray 完全是因 HTML5 canvas,而遗留的历史问题。除非必须要处理关于 canvas-y,否则要避免。
20.2.2 Handling overflow and underflow Normally, when a value is out of the range of the element type, modulo arithmetic is used to convert it to a value within range. For signed and unsigned integers that means that:
The highest value plus one is converted to the lowest value (0 for unsigned integers). The lowest value minus one is converted to the highest value. Modulo conversion for unsigned 8-bit integers:
处理 overflow 和 underflow
通常情况下,当一个值超出元素类型的范围时,会使用模数运算将其转换为范围内的值。对于有符号和无符号的整数,这意味着:当最高值加 1 被转换为最低值(无符号整数为0)最低值减 1 被转换为最高值。无符号 8 位整数的模数转换。
无符号 8 位整数的模数转换
const uint8 = new Uint8Array(1);
uint8[0] = 255; uint8[0] // 最大值在范围内
255
uint8[0] = 256; uint8[0] // 向上溢出
0
uint8[0] = 0; uint8[0] // 最小值在范围内
0
uint8[0] = -1; uint8[0] // 向下溢出
255
有符号 8 位整数的模数转换
const int8 = new Int8Array(1);
int8[0] = 127; int8[0] // 最大值在范围内
127
int8[0] = 128; int8[0] // 向上溢出
-128
int8[0] = -128; int8[0] // 最小值在范围内
-128
int8[0] = -129; int8[0] // 向下溢出
截断(Clamped)的转换是不同的。
- 将所有溢出的值转换为最低值
- 将所有溢出的值转换为最高值
const uint8c = new Uint8ClampedArray(1);
uint8c[0] = 255; uint8c[0] // highest value within range
255
uint8c[0] = 256; uint8c[0] // overflow
255
uint8c[0] = 0; uint8c[0] // lowest value within range
0
uint8c[0] = -1; uint8c[0] // underflow
0