diff --git a/files/zh-cn/web/javascript/guide/typed_arrays/index.md b/files/zh-cn/web/javascript/guide/typed_arrays/index.md
index 496db4062ea8e8..7e4eb0ae6f1330 100644
--- a/files/zh-cn/web/javascript/guide/typed_arrays/index.md
+++ b/files/zh-cn/web/javascript/guide/typed_arrays/index.md
@@ -5,25 +5,47 @@ slug: Web/JavaScript/Guide/Typed_arrays
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Using_promises", "Web/JavaScript/Guide/Iterators_and_generators")}}
-**JavaScript 类型化数组**(typed array)是一种类似数组的对象,并提供了一种用于在内存缓冲区中访问原始二进制数据的机制。
+JavaScript 类型化数组是一种类似数组的对象,并提供了一种用于在内存缓冲中访问原始二进制数据的机制。
-{{jsxref("Array")}} 存储的对象能动态增多和减少,并且可以存储任何 JavaScript 值。JavaScript 引擎会做一些内部优化,以便对数组的操作可以很快。然而,随着 Web 应用程序变得越来越强大,尤其一些新增加的功能例如:音频视频编辑、访问 WebSockets 的原始数据等,很明显有些时候如果使用 JavaScript 代码可以快速方便地通过类型化数组来操作原始的二进制数据将会非常有帮助。JavaScript 类型化数组中的每一个元素都是原始二进制值,而二进制值采用多种支持的格式之一(从 8 位整数到 64 位浮点数)。
+引入类型化数组并非是为了取代 JavaScript 中数组的任何一种功能。相反,它为开发者提供了一个操作二进制数据的接口。这在操作与平台相关的特性时会很有用,例如:音频视频编辑和访问 [WebSocket](/zh-CN/docs/Web/API/WebSockets_API) 原始数据等。JavaScript 类型化数组中的每一个元素都是以某种格式表示的原始二进制值,JavaScript 支持从 8 位整数到 64 位浮点数的多种二进制格式。
-但是,不要把类型化数组与普通数组混淆,因为在类型数组上调用 {{jsxref("Array.isArray()")}} 会返回 `false`。此外,并不是所有可用于普通数组的方法都能被类型化数组所支持(如 push 和 pop)。
+类型化数组拥有许多与数组相同的方法,语义也相似。但是,类型化数组并不是普通数组,因为在类型化数组上调用 {{jsxref("Array.isArray()")}} 会返回 `false`。此外,并不是所有可用于普通数组的方法都能被类型化数组所支持(如 push 和 pop)。
-## 缓冲和视图:类型数组架构
+为了最大程度的灵活性和效率,JavaScript 将类型化数组的实现拆分为*缓冲*和*视图*两部分。缓冲是一种表示了数据块的对象,它没有格式可言,也没有提供访问其内容的机制。为了访问缓冲中的内存,你需要使用[视图](#视图)。视图提供了*上下文*——即数据类型、起始偏移量和元素数量。
-为了达到最大的灵活性和效率,JavaScript 类型化数组将实现拆分为**缓冲**和**视图**两部分。缓冲(由 {{jsxref("ArrayBuffer")}} 对象实现)描述的是一个数据分块。缓冲没有格式可言,并且不提供访问其内容的机制。为了访问在缓冲对象中包含的内存,你需要使用视图。视图提供了上下文——即数据类型、起始偏移量和元素数——将数据转换为实际有类型的数组。
+![同一缓冲上的不同类型化数组。每种类型化数组的元素数量与元素宽度都不同。](typed_arrays.png)
-![ArrayBuffer 中的类型化数组](typed_arrays.png)
+## 缓冲
-### ArrayBuffer
+有两种类型的缓冲:{{jsxref("ArrayBuffer")}} 和 {{jsxref("SharedArrayBuffer")}}。它们都是内存块的低级表示。它们名字中都含有“array”,但是它们与数组并没有太多关系——你不能直接读写它们。相反,缓冲是通用的对象,它们只包含原始数据。为了访问缓冲所表示的内存,你需要使用视图。
-{{jsxref("ArrayBuffer")}} 是一种数据类型,用来表示一个通用的、固定长度的二进制数据缓冲区。你不能直接操作 ArrayBuffer 中的内容;你需要创建一个类型化数组的视图或一个描述缓冲数据格式的 {{jsxref("DataView")}},使用它们来读写缓冲区中的内容。
+缓冲支持以下操作:
+
+- _分配_:创建一个新的缓冲时,会分配一个新的内存块,并且初始化为 `0`。
+- _复制_:使用 {{jsxref("ArrayBuffer/slice", "slice()")}} 方法,你可以高效地复制缓冲中的一部分数据,而不需要创建视图来手动复制每一个字节。
+- _转移_:使用 {{jsxref("ArrayBuffer/transfer", "transfer()")}} 和 {{jsxref("ArrayBuffer/transferToFixedLength", "transferToFixedLength()")}} 方法,可以将内存块的所有权转移给一个新的缓冲对象。若你想要在不同的执行上下文间转移数据,又不想复制,这些方法就很有用。转移后,原始缓冲将不再可用。`SharedArrayBuffer` 不能被转移(因为缓冲已经被所有执行上下文共享)。
+- _调整大小_:使用 {{jsxref("ArrayBuffer/resize", "resize()")}} 方法,可以调整内存块的大小(只要不超过预设的 {{jsxref("ArrayBuffer/maxByteLength", "maxByteLength")}} 限制)。`SharedArrayBuffer` 只能[增长](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/grow),不能缩小。
+
+`ArrayBuffer` 与 `SharedArrayBuffer` 之间的区别是,前者在同一时刻只能所属于单个执行上下文。如果你将 `ArrayBuffer` 传递给另一个执行上下文,它会被*转移*,原始的 `ArrayBuffer` 将不再可用。这确保了同一时刻只有一个执行上下文可以访问内存。`SharedArrayBuffer` 在传递给另一个执行上下文时不会被转移,因此可以被多个执行上下文同时访问。当多个线程同时访问同一内存块时,可能会出现竞争条件,这时候 {{jsxref("Atomics")}} 方法就很有用了。
+
+## 视图
+
+目前主要有两种视图:类型化数组视图和 {{jsxref("DataView")}}。类型化数组提供了[实用方法](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#实例方法),可以方便地转换二进制数据。`DataView` 更底层,可以精确控制数据的访问方式。使用这两种视图读写数据的方式是非常不同的。
+
+两种视图都会使 {{jsxref("ArrayBuffer.isView()")}} 返回 `true`。它们都有以下属性:
+
+- `buffer`
+ - : 视图所引用的底层缓冲。
+- `byteOffset`
+ - : 视图相对于缓冲起始位置的偏移量(以字节为单位)。
+- `byteLength`
+ - : 视图的长度(以字节为单位)。
+
+两者的构造函数都接受上述三个分离的参数。类型化数组构造函数还接受 `length` 作为元素数量,而不是字节长度。
### 类型化数组视图
-类型化数组视图具有自描述性的名字和所有常用的数值类型像 `Int8`、`Uint32`、`Float64` 等等。有一种特殊类型的数组 `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 类型 |
| ------------------------------- | ---------------------------------------------- | ------ | ----------------------------------------------------- | --------------------- | ------------------------------- |
@@ -39,9 +61,67 @@ slug: Web/JavaScript/Guide/Typed_arrays
| {{jsxref("BigInt64Array")}} | -263~263 - 1 | 8 | 64 位有符号整数(补码) | `bigint` | `int64_t (signed long long)` |
| {{jsxref("BigUint64Array")}} | 0~264 - 1 | 8 | 64 位无符号整数 | `bigint` | `uint64_t (unsigned long long)` |
+所有类型化数组类型都有相同的方法与属性,这些方法与属性由 {{jsxref("TypedArray")}} 类定义。它们的唯一区别在于底层数据类型和字节数的不同。这在[值编码与标准化](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#值编码与标准化)中有详细讨论。
+
+类型化数组原则上是固定长度的,因此并不存在可以改变数组长度的方法,如 `pop`、`push`、`shift`、`splice` 和 `unshift`。此外,`flat` 也不可用,因为类型化数组无法嵌套;`concat` 和 `flatMap` 则是由于应用场景不大,亦不可用。由于 `splice` 不可用,因此 `toSpliced` 也不可用。所有其他数组方法都是 `Array` 和 `TypedArray` 共享的。
+
+另一方面,类型化数组有额外的 `set` 和 `subarray` 方法,可以用来优化“同缓冲多视图”的场景。`set()` 方法允许你使用一个数组或类型化数组的数据,来对另一个类型化数组的多个索引同时进行设置。如果两个类型化数组共享同一个底层缓冲,那么这个操作可能会更加高效,因为这是一个快速的内存移动。`subarray()` 方法创建一个新的类型化数组视图,它引用与原始类型化数组相同的缓冲,但是范围更窄。
+
+在不改变底层缓冲的前提下,无法直接改变类型化数组的长度。但是,当类型化数组的底层是可调整大小的缓冲,且没有固定的 `byteLength` 时,它就会*跟踪长度*,即它的长度会随着缓冲的大小而自动调整。详情请参阅[底层为可变大小缓冲时的行为](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#底层为可变大小缓冲时的行为)。
+
+类似于普通数组,你可以使用[方括号表示法](/zh-CN/docs/Web/JavaScript/Reference/Operators/Property_accessors#方括号表示法)来访问类型化数组的元素。底层缓冲中对应的字节会被解析为一个数字。任何使用数字(或数字的字符串表示,因为数字总是在访问属性时被转换为字符串)的属性访问都会被类型化数组代理——它们永远不会与对象本身交互。这意味着,例如:
+
+- 超越边界索引的访问总是返回 `undefined`,而不会实际访问对象上的属性。
+- 任何尝试写入超越边界的属性的行为都不会生效:它既不会抛出错误,也不会改变缓冲或类型化数组。
+- 类型化数组的索引看起来是可配置的和可写的,但是任何改变它们的属性的尝试都会失败。
+
+```js
+const uint8 = new Uint8Array([1, 2, 3]);
+console.log(uint8[0]); // 1
+
+// 仅用作示例。不要在生产代码中使用。
+uint8[-1] = 0;
+uint8[2.5] = 0;
+uint8[NaN] = 0;
+console.log(Object.keys(uint8)); // ["0", "1", "2"]
+console.log(uint8[NaN]); // undefined
+
+// 非数字访问仍然有效
+uint8[true] = 0;
+console.log(uint8[true]); // 0
+
+Object.freeze(uint8); // TypeError:无法冻结非空缓冲的视图
+```
+
### DataView
-{{jsxref("DataView")}} 是一种底层接口,它提供有可以操作缓冲区中任意数据的访问器(getter/setter)API。这对操作不同类型数据的场景很有帮助,例如:类型化数组视图都是运行在本地字节序模式(参考[字节序](/zh-CN/docs/Glossary/Endianness)),可以通过使用 `DataView` 来控制字节序。默认是大端字节序(Big-endian),但可以调用 getter/setter 方法改为小端字节序(Little-endian)。
+{{jsxref("DataView")}} 是一种底层接口,它提供可以操作缓冲中任意数据的 getter/setter API。这对操作不同类型数据的场景很有帮助,例如:类型化数组视图都是运行在本地字节序模式(参考[字节序](/zh-CN/docs/Glossary/Endianness)),可以通过使用 `DataView` 来控制字节序。默认是大端字节序(big-endian),但可以调用 getter/setter 方法改为小端字节序(little-endian)。
+
+`DataView` 不需要对齐,多字节读写可以从任意指定的偏移量开始。setter 方法也是如此。
+
+下面的例子使用 `DataView` 来获取任意数字的二进制表示:
+
+```js
+function toBinary(
+ x,
+ { type = "Float64", littleEndian = false, separator = " ", radix = 16 } = {},
+) {
+ const bytesNeeded = globalThis[`${type}Array`].BYTES_PER_ELEMENT;
+ const dv = new DataView(new ArrayBuffer(bytesNeeded));
+ dv[`set${type}`](0, x, littleEndian);
+ const bytes = Array.from({ length: bytesNeeded }, (_, i) =>
+ dv
+ .getUint8(i)
+ .toString(radix)
+ .padStart(8 / Math.log2(radix), "0"),
+ );
+ return bytes.join(separator);
+}
+
+console.log(toBinary(1.1)); // 3f f1 99 99 99 99 99 9a
+console.log(toBinary(1.1, { littleEndian: true })); // 9a 99 99 99 99 99 f1 3f
+console.log(toBinary(20, { type: "Int8", radix: 2 })); // 00010100
+```
## 使用类型化数组的 Web API
@@ -58,7 +138,7 @@ slug: Web/JavaScript/Guide/Typed_arrays
### 使用视图和缓冲
-首先,我们创建一个 16 字节固定长度的缓冲:
+首先,我们需要创建一个 16 字节固定长度的缓冲:
```js
const buffer = new ArrayBuffer(16);
@@ -68,13 +148,13 @@ const buffer = new ArrayBuffer(16);
```js
if (buffer.byteLength === 16) {
- console.log("Yes, it's 16 bytes.");
+ console.log("是 16 字节。");
} else {
- console.log("Oh no, it's the wrong size!");
+ console.log("大小有问题!");
}
```
-在实际开始操作这个缓冲之前,需要创建一个视图。我们将创建一个视图,此视图将把缓冲内的数据格式化为一个 32 位有符号整数数组:
+在实际开始操作这个缓冲之前,还需要一个视图。现在,我们就创建一个视图,该视图将把缓冲内的数据视为一个 32 位有符号整数数组:
```js
const int32View = new Int32Array(buffer);
@@ -90,28 +170,73 @@ for (let i = 0; i < int32View.length; i++) {
该代码会将数组以 `0`、`2`、`4` 和 `6` 填充(一共 4 个 4 字节元素,所以总长度为 16 字节)。
-### 同一数据的多个视图
+### 相同数据上的多个视图
-更有意思的是,你可以在同一数据上创建多个视图。例如:基于上文的代码,我们可以添加如下代码处理:
+更有意思的是,你可以在同一数据上创建多个视图。例如:基于上文的代码,我们可以像这样继续操作:
```js
const int16View = new Int16Array(buffer);
for (let i = 0; i < int16View.length; i++) {
- console.log(`Entry ${i}: ${int16View[i]}`);
+ console.log(`索引 ${i}:${int16View[i]}`);
}
```
-这里我们创建了一个 16 位整数视图,该视图共享上文的 32 位整数视图的缓冲,然后以 16 位整数打印出缓冲里的数据,这次我们会得到 `0`、`0`、`2`、`0`、`4`、`0`、`6`、`0` 这样的输出。
+这里我们创建了一个 16 位整数视图,该视图共享上文的 32 位整数视图的缓冲,然后以 16 位整数打印出缓冲里的数据,这次我们会得到 `0`、`0`、`2`、`0`、`4`、`0`、`6`、`0` 这样的输出(假设是小端序编码)。
+
+```plain
+Int16Array | 0 | 0 | 2 | 0 | 4 | 0 | 6 | 0 |
+Int32Array | 0 | 2 | 4 | 6 |
+ArrayBuffer | 00 00 00 00 | 02 00 00 00 | 04 00 00 00 | 06 00 00 00 |
+```
-那么,这样呢?
+进一步地:
```js
int16View[0] = 32;
-console.log(`Entry 0 in the 32-bit array is now ${int32View[0]}`);
+console.log(`32 位数组的索引 0 处数据是:${int32View[0]}`);
+```
+
+这次的输出是 `"32 位数组的索引 0 处数据是:32"`。也就是,这 2 个数组都是同一数据的以不同格式展示出来的视图。
+
+```plain
+Int16Array | 32 | 0 | 2 | 0 | 4 | 0 | 6 | 0 |
+Int32Array | 32 | 2 | 4 | 6 |
+ArrayBuffer | 00 02 00 00 | 02 00 00 00 | 04 00 00 00 | 06 00 00 00 |
+```
+
+你可以对任意视图类型进行这样的操作,尽管如果你设置一个整数,然后以浮点数的形式读取它,你可能会得到一个奇怪的结果,因为位的解释方式不同。
+
+```js
+const float32View = new Float32Array(buffer);
+console.log(float32View[0]); // 4.484155085839415e-44
+```
+
+### 从缓冲读取文本
+
+缓冲并不总是表示数字。例如,读取文件可以给你一个文本数据缓冲。你可以使用类型化数组从缓冲中读取这些数据。
+
+下面的代码使用 {{domxref("TextDecoder")}} web API 读取 UTF-8 文本:
+
+```js
+const buffer = new ArrayBuffer(8);
+const uint8 = new Uint8Array(buffer);
+// 我们手动写入数据,假装它已经在缓冲区中了
+uint8.set([228, 189, 160, 229, 165, 189]);
+const text = new TextDecoder().decode(uint8);
+console.log(text); // "你好"
```
-这次的输出是 `"Entry 0 in the 32-bit array is now 32"`。也就是,这 2 个数组都是同一数据的以不同格式展示出来的视图。你可以使用任何一种[视图类型](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_对象)。
+下面的代码使用 {{jsxref("String.fromCharCode()")}} 方法读取 UTF-16 文本:
+
+```js
+const buffer = new ArrayBuffer(8);
+const uint16 = new Uint16Array(buffer);
+// 我们手动写入数据,假装它已经在缓冲区中了
+uint16.set([0x4f60, 0x597d]);
+const text = String.fromCharCode(...uint16);
+console.log(text); // "你好"
+```
### 使用复杂的数据结构
@@ -132,20 +257,20 @@ struct someStruct {
```js
const buffer = new ArrayBuffer(24);
-// ... read the data into the buffer ...
+// …将数据读入缓冲…
const idView = new Uint32Array(buffer, 0, 1);
const usernameView = new Uint8Array(buffer, 4, 16);
const amountDueView = new Float32Array(buffer, 20, 1);
```
-现在你就可以通过 `amountDueView[0]` 的方式访问数据。
+这样一来,你就得到了一个类似的数据结构,例如,`amountDueView[0]` 对应了 C 的 `amountDue` 字段。
-> **备注:** C 语言结构体的[数据对齐](https://zh.wikipedia.org/wiki/数据结构对齐)与平台相关。因此需要防范和考虑不同平台字节填充对齐的差异。
+> **备注**:C 语言结构体的[数据对齐](https://zh.wikipedia.org/wiki/数据结构对齐)与平台相关。因此需要防范和考虑不同平台字节填充对齐的差异。
### 转换为普通数组
-在处理完一个类型化数组后,有时需要把它转为普通数组,以便可以从 {{jsxref("Array")}} 原型中受益。可以使用 {{jsxref("Array.from()")}} 实现:
+在处理完一个类型化数组后,有时需要把它转为普通数组,以便可以从 {{jsxref("Array")}} 原型中受益。可以通过使用 {{jsxref("Array.from()")}} 实现:
```js
const typedArray = new Uint8Array([1, 2, 3, 4]);
@@ -159,18 +284,14 @@ const typedArray = new Uint8Array([1, 2, 3, 4]);
const normalArray = [...typedArray];
```
-如果不支持 `Array.from()`,还可以使用以下代码。
-
-```js
-const typedArray = new Uint8Array([1, 2, 3, 4]);
-const normalArray = Array.prototype.slice.call(typedArray);
-```
-
## 参见
-- [从 Base64 编码的字符串获取 `ArrayBuffer` 或类型化数组](/zh-CN/docs/Glossary/Base64#appendix_decode_a_base64_string_to_uint8array_or_arraybuffer)
- [使用类型化数组实现快速的 Canvas 像素操作](https://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipulation-with-typed-arrays/)
- [类型化数组:浏览器中的二进制数据](https://web.dev/articles/webgl-typed-arrays)
- [字节序](/zh-CN/docs/Glossary/Endianness)
+- {{jsxref("ArrayBuffer")}}
+- {{jsxref("DataView")}}
+- {{jsxref("TypedArray")}}
+- {{jsxref("SharedArrayBuffer")}}
{{PreviousNext("Web/JavaScript/Guide/Using_promises", "Web/JavaScript/Guide/Iterators_and_generators")}}
diff --git a/files/zh-cn/web/javascript/reference/global_objects/arraybuffer/index.md b/files/zh-cn/web/javascript/reference/global_objects/arraybuffer/index.md
index 312637b31f5d19..2e60373f88d3c3 100644
--- a/files/zh-cn/web/javascript/reference/global_objects/arraybuffer/index.md
+++ b/files/zh-cn/web/javascript/reference/global_objects/arraybuffer/index.md
@@ -13,6 +13,14 @@ slug: Web/JavaScript/Reference/Global_Objects/ArrayBuffer
`ArrayBuffer` 是一个[可转移对象](/zh-CN/docs/Web/API/Web_Workers_API/Transferable_objects)。
+## 描述
+
+### 调整 ArrayBuffer 的大小
+
+`ArrayBuffer` 对象可以通过在调用 {{jsxref("ArrayBuffer/ArrayBuffer", "ArrayBuffer()")}} 构造函数时包含 `maxByteLength` 选项来使其大小可变。你可以通过访问其 {{jsxref("ArrayBuffer/resizable", "resizable")}} 和 {{jsxref("ArrayBuffer/maxByteLength", "maxByteLength")}} 属性来查询 `ArrayBuffer` 的大小是否可变以及其最大值。你可以通过调用 {{jsxref("ArrayBuffer/resize", "resize()")}} 为可变大小的 `ArrayBuffer` 分配一个新的大小。新的字节会被初始化为 0。
+
+这些特性使得调整 `ArrayBuffer` 的大小更加高效——否则,你必须使用新的大小创建一个缓冲副本。这也使得 JavaScript 在这方面与 WebAssembly 相当(Wasm 线性内存可以使用 [`WebAssembly.Memory.prototype.grow()`](/zh-CN/docs/WebAssembly/JavaScript_interface/Memory/grow) 调整大小)。
+
## 构造函数
- {{jsxref("ArrayBuffer.ArrayBuffer", "ArrayBuffer()")}}
@@ -62,6 +70,6 @@ const view = new Int32Array(buffer);
## 参见
- [`core-js` 中的 `ArrayBuffer` Polyfill](https://github.com/zloirock/core-js#ecmascript-typed-arrays)
-- [JavaScript 类型化数组](/zh-CN/docs/Web/JavaScript/Typed_arrays)
+- [JavaScript 类型化数组](/zh-CN/docs/Web/JavaScript/Guide/Typed_arrays)
- {{jsxref("SharedArrayBuffer")}}
- [RangeError:无效的数组长度](/zh-CN/docs/Web/JavaScript/Reference/Errors/Invalid_array_length)
diff --git a/files/zh-cn/web/javascript/reference/global_objects/typedarray/index.md b/files/zh-cn/web/javascript/reference/global_objects/typedarray/index.md
index 1b2b13e4d7234c..774c0c1fd49430 100644
--- a/files/zh-cn/web/javascript/reference/global_objects/typedarray/index.md
+++ b/files/zh-cn/web/javascript/reference/global_objects/typedarray/index.md
@@ -31,6 +31,93 @@ slug: Web/JavaScript/Reference/Global_Objects/TypedArray
| {{jsxref("BigInt64Array")}} | -263 到 263 - 1 | 8 | 64 位有符号整型(补码) | `bigint` | `int64_t (signed long long)` |
| {{jsxref("BigUint64Array")}} | 0 到 264 - 1 | 8 | 64 位无符号整型 | `bigint` | `uint64_t (unsigned long long)` |
+### 值编码与标准化
+
+所有的类型化数组都是基于 `ArrayBuffer` 进行操作的,你可以借此观察到每个元素的确切字节表示,因此二进制格式中的数字编码方式具有重要意义。
+
+- 无符号整数数组(`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` 一样以二进制形式存储数字,但是当你存储超出范围的数字时,它会将数字*钳制*(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`。
+- `Float32Array` 使用“银行家舍入法”将 64 位浮点数转换为 32 位。这与 {{jsxref("Math.fround()")}} 提供的算法相同。
+
+### 底层为可变大小缓冲时的行为
+
+当一个 `TypedArray` 被创建为一个[可变大小缓冲](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer#调整_arraybuffer_的大小)的视图时,改变底层缓冲的大小会对 `TypedArray` 的大小产生不同的影响,这取决于 `TypedArray` 是否是长度跟踪的。
+
+如果一个类型化数组是通过省略或传递 `undefined` 给第三个参数来创建的,那么它将*跟踪长度*,并且将自动调整大小以适应底层 `buffer` 的大小:
+
+```js
+const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
+const float32 = new Float32Array(buffer);
+
+console.log(float32.byteLength); // 8
+console.log(float32.length); // 2
+
+buffer.resize(12);
+
+console.log(float32.byteLength); // 12
+console.log(float32.length); // 3
+```
+
+如果一个类型化数组是通过使用第三个 `length` 参数指定大小创建时,则它的大小不会随着 `buffer` 大小的增长而改变:
+
+```js
+const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
+const float32 = new Float32Array(buffer, 0, 2);
+
+console.log(float32.byteLength); // 8
+console.log(float32.length); // 2
+console.log(float32[0]); // 0, 初始值
+
+buffer.resize(12);
+
+console.log(float32.byteLength); // 8
+console.log(float32.length); // 2
+console.log(float32[0]); // 0, 初始值
+```
+
+当 `buffer` 缩小时,其上的类型化数组可能会超出范围,在这种情况下,类型化数组的观测大小将减少为 0。这是非长度跟踪类型化数组唯一可能改变长度的情况。
+
+```js
+const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
+const float32 = new Float32Array(buffer, 0, 2);
+
+buffer.resize(7);
+
+console.log(float32.byteLength); // 0
+console.log(float32.length); // 0
+console.log(float32[0]); // undefined
+```
+
+如果你随后再次增长 `buffer` 以使类型化数组回到范围内,类型化数组的大小将恢复到其原始值。
+
+```js
+buffer.resize(8);
+
+console.log(float32.byteLength); // 8
+console.log(float32.length); // 2
+console.log(float32[0]); // 0 - 又回到范围内了!
+```
+
+对于长度跟踪的类型化数组,如果 `buffer` 被缩小到小于 `byteOffset`,也会发生同样的事情。
+
+```js
+const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
+const float32 = new Float32Array(buffer, 4);
+// float32 是长度跟踪的,但它只从第 4 个字节开始,直到缓冲的结尾,
+// 所以如果缓冲被缩小到小于 4 个字节,类型化数组就将超出范围
+buffer.resize(3);
+console.log(float32.byteLength); // 0
+```
+
## 构造函数
该对象不能被直接实例化——试图去使用 `new` 构造它将会抛出 {{jsxref("TypeError")}}。
@@ -259,7 +346,7 @@ const i32 = new Int32Array(new ArrayBuffer(4));
## 参见
- [`core-js` 中类型化数组的 polyfill](https://github.com/zloirock/core-js#ecmascript-typed-arrays)
-- [JavaScript 类型化数组](/zh-CN/docs/Web/JavaScript/Typed_arrays)
+- [JavaScript 类型化数组](/zh-CN/docs/Web/JavaScript/Guide/Typed_arrays)
- {{jsxref("ArrayBuffer")}}
- {{jsxref("DataView")}}
- [TextDecoder](/zh-CN/docs/Web/API/TextDecoder)——从数字数据中解码字符串的助手