Skip to content

Commit

Permalink
resolve conversation
Browse files Browse the repository at this point in the history
  • Loading branch information
AquanJSW committed Nov 2, 2023
1 parent 21cec4b commit ab87d0c
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 14 deletions.
18 changes: 9 additions & 9 deletions files/zh-cn/web/javascript/guide/typed_arrays/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ slug: Web/JavaScript/Guide/Typed_arrays

JavaScript 类型化数组是一种类似数组的对象,并提供了一种用于在内存缓冲中访问原始二进制数据的机制。

引入类型化数组并非是为了取代 JavaScript 中数组的任何一种功能。相反,它为开发者提供了一个操作二进制数据的接口。这在操作与平台相关的特性时会很有用,例如:音频视频编辑和访问 [WebSockets](/zh-CN/docs/Web/API/WebSockets_API) 原始数据等。JavaScript 类型化数组中的每一个元素都是以某种格式表示的原始二进制值,JavaScript 支持从 8 位整数到 64 位浮点数的多种二进制格式。
引入类型化数组并非是为了取代 JavaScript 中数组的任何一种功能。相反,它为开发者提供了一个操作二进制数据的接口。这在操作与平台相关的特性时会很有用,例如:音频视频编辑和访问 [WebSocket](/zh-CN/docs/Web/API/WebSockets_API) 原始数据等。JavaScript 类型化数组中的每一个元素都是以某种格式表示的原始二进制值,JavaScript 支持从 8 位整数到 64 位浮点数的多种二进制格式。

类型化数组拥有许多与数组相同的方法,语义也相似。但是,类型化数组并不是普通数组,因为在类型化数组上调用 {{jsxref("Array.isArray()")}} 会返回 `false`。此外,并不是所有可用于普通数组的方法都能被类型化数组所支持(如 push 和 pop)。

为了最大程度的灵活性和效率,JavaScript 将类型化数组的实现拆分为*缓冲**视图*两部分。缓冲是一种表示了数据块的对象,它没有格式可言,也没有提供访问其内容的机制。为了访问缓冲中的内存,你需要使用[视图](#views)。视图提供了*上下文*——即数据类型、起始偏移量和元素数量。
为了最大程度的灵活性和效率,JavaScript 将类型化数组的实现拆分为*缓冲**视图*两部分。缓冲是一种表示了数据块的对象,它没有格式可言,也没有提供访问其内容的机制。为了访问缓冲中的内存,你需要使用[视图](#视图)。视图提供了*上下文*——即数据类型、起始偏移量和元素数量。

![同一缓冲上的不同类型化数组。每种类型化数组的元素数量与元素宽度都不同。](typed_arrays.png)

## 缓冲

有两种类型的缓冲:{{jsxref("ArrayBuffer")}} 和 {{jsxref("SharedArrayBuffer")}}。它们都是内存块的低级表示。他们名字中都含有“array”,但是它们与数组并没有太多关系——你不能直接读写它们。相反,缓冲是通用的对象,它们只包含原始数据。为了访问缓冲所表示的内存,你需要使用视图。
有两种类型的缓冲:{{jsxref("ArrayBuffer")}} 和 {{jsxref("SharedArrayBuffer")}}。它们都是内存块的低级表示。它们名字中都含有“array”,但是它们与数组并没有太多关系——你不能直接读写它们。相反,缓冲是通用的对象,它们只包含原始数据。为了访问缓冲所表示的内存,你需要使用视图。

缓冲支持以下操作:

Expand Down Expand Up @@ -45,7 +45,7 @@ JavaScript 类型化数组是一种类似数组的对象,并提供了一种用

### 类型化数组视图

类型化数组视图有自描述的名称,并且提供了所有常见数值类型的视图,如 `Int8``Uint32``Float64` 等等。还有一种特殊的类型化数组视图,{{jsxref("Uint8ClampedArray")}},它会将值夹挤到 `0``255` 之间,这在 [Canvas 数据处理](/zh-CN/docs/Web/API/ImageData)等场景中很有用。
类型化数组视图有自描述的名称,并且提供了所有常见数值类型的视图,如 `Int8``Uint32` `Float64` 等等。还有一种特殊的类型化数组视图,{{jsxref("Uint8ClampedArray")}},它会将值钳制(clamp)到 `0``255` 之间,这在 [Canvas 数据处理](/zh-CN/docs/Web/API/ImageData)等场景中很有用。

| 类型 | 值范围 | 字节数 | 描述 | 对应的 Web IDL 类型 | 等效的 C 类型 |
| ------------------------------- | ---------------------------------------------- | ------ | ----------------------------------------------------- | --------------------- | ------------------------------- |
Expand Down Expand Up @@ -90,7 +90,7 @@ console.log(uint8[NaN]); // undefined
uint8[true] = 0;
console.log(uint8[true]); // 0

Object.freeze(uint8); // TypeError: 无法冻结非空缓冲的视图
Object.freeze(uint8); // TypeError无法冻结非空缓冲的视图
```

### DataView
Expand Down Expand Up @@ -138,7 +138,7 @@ console.log(toBinary(20, { type: "Int8", radix: 2 })); // 00010100

### 使用视图和缓冲

首先,我们需要一个缓冲,这里我们创建一个 16 字节固定长度的缓冲:
首先,我们需要创建一个 16 字节固定长度的缓冲:

```js
const buffer = new ArrayBuffer(16);
Expand Down Expand Up @@ -178,7 +178,7 @@ for (let i = 0; i < int32View.length; i++) {
const int16View = new Int16Array(buffer);

for (let i = 0; i < int16View.length; i++) {
console.log(`索引 ${i}: ${int16View[i]}`);
console.log(`索引 ${i}${int16View[i]}`);
}
```

Expand Down Expand Up @@ -257,14 +257,14 @@ struct someStruct {
```js
const buffer = new ArrayBuffer(24);
// ... 将数据读入缓冲 ...
// 将数据读入缓冲
const idView = new Uint32Array(buffer, 0, 1);
const usernameView = new Uint8Array(buffer, 4, 16);
const amountDueView = new Float32Array(buffer, 20, 1);
```

这样一来,你就得到了一个类似的数据结构,例如,`amountDueView[0]` 对应了 C 的`amountDue` 字段。
这样一来,你就得到了一个类似的数据结构,例如,`amountDueView[0]` 对应了 C 的 `amountDue` 字段。

> **备注**:C 语言结构体的[数据对齐](https://zh.wikipedia.org/wiki/数据结构对齐)与平台相关。因此需要防范和考虑不同平台字节填充对齐的差异。

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,22 @@ slug: Web/JavaScript/Reference/Global_Objects/TypedArray

- 无符号整数数组(`Uint8Array``Uint16Array``Uint32Array``BigUint64Array`)直接以二进制形式存储数字。
- 有符号整数数组(`Int8Array``Int16Array``Int32Array``BigInt64Array`)使用[二进制补码](https://zh.wikipedia.org/zh-cn/二補數)存储数字。
- 浮点数组(`Float32Array``Float64Array`)使用[IEEE 754](https://zh.wikipedia.org/zh-cn/IEEE_754)浮点格式存储数字。[`Number`](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number#number_编码) 参考文档中有关于确切格式的更多信息。JavaScript 数字默认使用双精度浮点格式,这与 `Float64Array` 相同。`Float32Array` 使用 23(而不是 52)位用于尾数,以及 8(而不是 11)位用于指数。请注意,规范要求所有的 {{jsxref("NaN")}} 值使用相同的位编码,但确切的位模式取决于实现。
- `Uint8ClampedArray` 是一种特殊情况。它像 `Uint8Array` 一样以二进制形式存储数字,但是当你存储超出范围的数字时,它会将数字*夹挤*到 0 到 255 的范围内,而不是截断最高有效位。
- 浮点数组(`Float32Array``Float64Array`)使用 [IEEE 754](https://zh.wikipedia.org/zh-cn/IEEE_754)浮点格式存储数字。[`Number`](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number#number_编码) 参考文档中有关于确切格式的更多信息。JavaScript 数字默认使用双精度浮点格式,这与 `Float64Array` 相同。`Float32Array` 23(而不是 52)位用于尾数,以及 8(而不是 11)位用于指数。请注意,规范要求所有的 {{jsxref("NaN")}} 值使用相同的位编码,但确切的位模式取决于实现。
- `Uint8ClampedArray` 是一种特殊情况。它像 `Uint8Array` 一样以二进制形式存储数字,但是当你存储超出范围的数字时,它会将数字*钳制*(clamp)到 0 到 255 的范围内,而不是截断最高有效位。

除了 `Int8Array``Unit8Array``Uint8ClampedArray` 以外的其他类型数组都将每个元素存储为多个字节。这些字节可以按照从最高有效位到最低有效位(大端序)或从最低有效位到最高有效位(小端序)的顺序进行排序。请参阅[字节序](/zh-CN/docs/Glossary/Endianness)以了解更多。类型化数组始终使用平台的本机字节顺序。如果要在缓冲区中写入和读取时指定字节顺序,应该使用 {{jsxref("DataView")}}。

当向这些类型化数组写入时,超出可表示范围的值将被标准化。

- 所有整数数组(`Uint8ClampedArray` 除外)都使用[固定宽度数值转换](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number#固定宽度数值转换),首先截断数字的小数部分,然后取最低位。
- `Uint8ClampedArray` 首先将数字夹挤到 0 到 255 的范围内(大于 255 的值变为 255,小于 0 的值变为 0),然后使用银行家舍入法将结果*四舍五入*(而非向下取整)到最近的整数,也就是说,如果数字恰好在两个整数之间,它将四舍五入到最近的偶数。例如,`0.5` 变为 `0``1.5` 变为 `2``2.5` 变为 `2`
- `Uint8ClampedArray` 首先将数字钳制到 0 到 255 的范围内(大于 255 的值变为 255,小于 0 的值变为 0),然后使用银行家舍入法将结果*四舍五入*(而非向下取整)到最近的整数,也就是说,如果数字恰好在两个整数之间,它将四舍五入到最近的偶数。例如,`0.5` 变为 `0``1.5` 变为 `2``2.5` 变为 `2`
- `Float32Array` 使用“银行家舍入法”将 64 位浮点数转换为 32 位。这与 {{jsxref("Math.fround()")}} 提供的算法相同。

### 底层为可变大小缓冲时的行为

当一个 `TypedArray` 被创建为一个[可变大小缓冲](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer#调整_ArrayBuffer_的大小)的视图时,改变底层缓冲的大小会对 `TypedArray` 的大小产生不同的影响,这取决于 `TypedArray` 是否是长度跟踪的。
当一个 `TypedArray` 被创建为一个[可变大小缓冲](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer#调整_arraybuffer_的大小)的视图时,改变底层缓冲的大小会对 `TypedArray` 的大小产生不同的影响,这取决于 `TypedArray` 是否是长度跟踪的。

如果一个类型化数组是通过省略或传递 `undefined` 给第三个参数来创建的,那么它将成为*长度跟踪*,并且将自动调整大小以适应底层 `buffer` 的大小:
如果一个类型化数组是通过省略或传递 `undefined` 给第三个参数来创建的,那么它将*跟踪长度*,并且将自动调整大小以适应底层 `buffer` 的大小:

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
Expand Down

0 comments on commit ab87d0c

Please sign in to comment.