TypedArray

Baseline 广泛可用 *

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

* 此特性的某些部分可能存在不同级别的支持。

一个 TypedArray 对象描述了底层二进制数据缓冲区的类数组视图。没有名为 TypedArray 的全局属性,也没有直接可见的 TypedArray 构造函数。相反,有许多不同的全局属性,其值是针对特定元素类型的类型化数组构造函数,如下所示。在以下页面中,你将找到可与包含任何类型的元素的任何类型化数组一起使用的常用属性和方法。

描述

TypedArray 构造函数(通常称为 %TypedArray% 以表示其“内在性”,因为它不对应于任何暴露给 JavaScript 程序的全局对象)作为所有 TypedArray 子类的共同超类。可以将 %TypedArray% 视为一个“抽象类”,为所有类型化数组子类提供通用实用方法接口。此构造函数不直接公开:没有全局 TypedArray 属性。它只能通过 Object.getPrototypeOf(Int8Array) 等方式访问。

创建 TypedArray 子类(例如 Int8Array)的实例时,会在内存中内部创建一个数组缓冲区,或者,如果将 ArrayBuffer 对象作为构造函数参数给出,则使用该 ArrayBuffer。缓冲区地址作为实例的内部属性保存,并且 %TypedArray%.prototype 的所有方法都将根据该数组缓冲区地址设置和获取值。

TypedArray 对象

类型 值范围 大小(字节) Web IDL 类型
Int8Array -128 到 127 1 byte
Uint8Array 0 到 255 1 octet
Uint8ClampedArray 0 到 255 1 octet
Int16Array -32768 到 32767 2 short
Uint16Array 0 到 65535 2 unsigned short
Int32Array -2147483648 到 2147483647 4 long
Uint32Array 0 到 4294967295 4 unsigned long
Float16Array -6550465504 2 N/A
Float32Array -3.4e383.4e38 4 unrestricted float
Float64Array -1.8e3081.8e308 8 无限制双精度
BigInt64Array -263 到 263 - 1 8 bigint
BigUint64Array 0 到 264 - 1 8 bigint

值编码和规范化

所有类型化数组都在 ArrayBuffer 上操作,你可以在其中观察每个元素的精确字节表示,因此数字在二进制格式中的编码方式非常重要。

  • 无符号整数数组(Uint8ArrayUint16ArrayUint32ArrayBigUint64Array)直接以二进制形式存储数字。
  • 有符号整数数组(Int8ArrayInt16ArrayInt32ArrayBigInt64Array)使用二进制补码存储数字。
  • 浮点数组(Float16ArrayFloat32ArrayFloat64Array)使用IEEE 754 浮点格式存储数字。Number 引用中有关于精确格式的更多信息。JavaScript 数字默认使用双精度浮点格式,这与 Float64Array 相同。Float32Array 使用 23 位(而不是 52 位)表示尾数,8 位(而不是 11 位)表示指数。Float16Array 使用 10 位表示尾数,5 位表示指数。请注意,规范要求所有NaN 值使用相同的位编码,但确切的位模式取决于实现。
  • Uint8ClampedArray 是一个特殊情况。它像 Uint8Array 一样以二进制形式存储数字,但是当存储超出范围的数字时,它会通过数学值将数字“钳制”到 0 到 255 的范围,而不是截断最高有效位。

Int8ArrayUint8ArrayUint8ClampedArray 之外的所有类型化数组都使用多个字节存储每个元素。这些字节可以从最高有效到最低有效(大端序)或从最低有效到最高有效(小端序)排序。有关更多说明,请参阅字节序。类型化数组始终使用平台的本机字节序。如果要在从缓冲区写入和读取时指定字节序,则应改用 DataView

写入这些类型化数组时,超出可表示范围的值将进行规范化。

  • 所有整数数组(Uint8ClampedArray 除外)都使用固定宽度数字转换,它首先截断数字的小数部分,然后取最低位。
  • Uint8ClampedArray 首先将数字钳制到 0 到 255 的范围(大于 255 的值变为 255,小于 0 的值变为 0)。然后它将结果“四舍五入”(而不是向下取整)到最接近的整数,采用半舍到偶数;这意味着如果数字恰好介于两个整数之间,它将四舍五入到最接近的偶数整数。例如,0.5 变为 01.5 变为 22.5 变为 2
  • Float16ArrayFloat32Array 执行“四舍五入到偶数”以将 64 位浮点数转换为 32 位和 16 位。这与 Math.fround()Math.f16round() 提供的算法相同。

查看可调整大小的缓冲区时的行为

TypedArray 作为可调整大小的缓冲区的视图创建时,调整底层缓冲区的大小将对 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 的增长而调整大小以包含 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, the initial value

buffer.resize(12);

console.log(float32.byteLength); // 8
console.log(float32.length); // 2
console.log(float32[0]); // 0, the initial value

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 - back in bounds again!

如果缓冲区缩小到 byteOffset 之外,长度跟踪类型化数组也可能发生同样的情况。

js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const float32 = new Float32Array(buffer, 4);
// float32 is length-tracking, but it only extends from the 4th byte
// to the end of the buffer, so if the buffer is resized to be shorter
// than 4 bytes, the typed array will become out of bounds
buffer.resize(3);
console.log(float32.byteLength); // 0

构造函数

此对象无法直接实例化 — 尝试使用 new 构造它会抛出 TypeError

js
new (Object.getPrototypeOf(Int8Array))();
// TypeError: Abstract class TypedArray not directly constructable

相反,你创建特定类型的类型化数组实例,例如 Int8ArrayBigInt64Array。这些对象都有一个共同的构造函数语法。

js
new TypedArray()
new TypedArray(length)
new TypedArray(typedArray)
new TypedArray(object)

new TypedArray(buffer)
new TypedArray(buffer, byteOffset)
new TypedArray(buffer, byteOffset, length)

其中 TypedArray 是具体类型之一的构造函数。

注意:所有 TypedArray 子类的构造函数都只能通过 new 来构造。尝试在没有 new 的情况下调用其中一个会抛出 TypeError

参数

typedArray

当使用 TypedArray 子类的实例调用时,typedArray 会被复制到一个新的类型化数组中。对于非 bigint TypedArray 构造函数,typedArray 参数只能是以下非 bigint 类型之一(例如 Int32Array)。类似地,对于 bigint TypedArray 构造函数(BigInt64ArrayBigUint64Array),typedArray 参数只能是以下 bigint 类型之一。typedArray 中的每个值在复制到新数组之前都会转换为构造函数的相应类型。新类型化数组的长度将与 typedArray 参数的长度相同。

object

当使用非 TypedArray 实例的对象调用时,将以与 TypedArray.from() 方法相同的方式创建一个新的类型化数组。

length 可选

当使用非对象调用时,参数将被视为指定类型化数组长度的数字。内存中会创建一个内部数组缓冲区,大小为 length 乘以 BYTES_PER_ELEMENT 字节,并用零填充。省略所有参数等同于使用 0 作为 length

bufferbyteOffset 可选length 可选

当使用 ArrayBufferSharedArrayBuffer 实例调用时,以及可选的 byteOffsetlength 参数,将创建一个新的类型化数组视图来查看指定的缓冲区。byteOffset(以字节为单位)和 length(以元素数量为单位,每个元素占用 BYTES_PER_ELEMENT 字节)参数指定类型化数组视图将公开的内存范围。如果两者都省略,则查看 buffer 的全部内容;如果只省略 length,则查看从 byteOffset 开始的 buffer 的剩余部分。如果省略 length,则类型化数组将变为长度跟踪

异常

所有 TypeArray 子类构造函数都以相同的方式操作。它们都会抛出以下异常:

TypeError

在以下情况之一中抛出

  • 传入了一个 typedArray,但它是一个 bigint 类型,而当前构造函数不是,反之亦然。
  • 传入了一个 typedArray,但它正在查看的缓冲区已分离,或者直接传入了一个已分离的 buffer
RangeError

在以下情况之一中抛出

  • 新类型化数组的长度过大。
  • buffer 的长度(如果未指定 length 参数)或 byteOffset 不是新类型化数组元素大小的整数倍。
  • byteOffset 不是有效的数组索引(一个介于 0 和 253 - 1 之间的整数)。
  • 从缓冲区创建视图时,边界超出缓冲区。换句话说,byteOffset + length * TypedArray.BYTES_PER_ELEMENT > buffer.byteLength

静态属性

这些属性在 TypedArray 构造函数对象上定义,因此由所有 TypedArray 子类构造函数共享。

TypedArray[Symbol.species]

用于创建派生对象的构造函数。

所有 TypedArray 子类还具有以下静态属性:

TypedArray.BYTES_PER_ELEMENT

返回不同 TypedArray 对象的元素大小的数字值。

静态方法

这些方法在 TypedArray 构造函数对象上定义,因此由所有 TypedArray 子类构造函数共享。

TypedArray.from()

从类数组或可迭代对象创建新的 TypedArray。另请参见 Array.from()

TypedArray.of()

使用可变数量的参数创建新的 TypedArray。另请参见 Array.of()

实例属性

这些属性在 TypedArray.prototype 上定义,并由所有 TypedArray 子类实例共享。

TypedArray.prototype.buffer

返回类型化数组引用的 ArrayBuffer

TypedArray.prototype.byteLength

返回类型化数组的长度(以字节为单位)。

TypedArray.prototype.byteOffset

返回类型化数组相对于其 ArrayBuffer 起始位置的偏移量(以字节为单位)。

TypedArray.prototype.constructor

创建实例对象的构造函数。TypedArray.prototype.constructor 是隐藏的 TypedArray 构造函数,但每个类型化数组子类也定义了自己的 constructor 属性。

TypedArray.prototype.length

返回类型化数组中包含的元素数量。

TypedArray.prototype[Symbol.toStringTag]

TypedArray.prototype[Symbol.toStringTag] 属性的初始值是一个 getter,它返回与类型化数组构造函数名称相同的字符串。如果 this 值不是类型化数组子类之一,则返回 undefined。此属性用于 Object.prototype.toString()。但是,由于 TypedArray 也有自己的 toString() 方法,因此除非你使用类型化数组作为 thisArg 调用 Object.prototype.toString.call(),否则不会使用此属性。

所有 TypedArray 子类还具有以下实例属性

TypedArray.prototype.BYTES_PER_ELEMENT

返回不同 TypedArray 对象的元素大小的数字值。

实例方法

这些方法在 TypedArray 原型对象上定义,因此由所有 TypedArray 子类实例共享。

TypedArray.prototype.at()

接受一个整数值并返回该索引处的项。此方法允许使用负整数,这些整数从最后一项开始倒数。

TypedArray.prototype.copyWithin()

在数组内复制一系列数组元素。另请参见 Array.prototype.copyWithin()

TypedArray.prototype.entries()

返回一个新的“数组迭代器”对象,其中包含数组中每个索引的键/值对。另请参见 Array.prototype.entries()

TypedArray.prototype.every()

如果数组中存在一个不满足所提供测试函数的元素,则返回 false。否则,返回 true。另请参见 Array.prototype.every()

TypedArray.prototype.fill()

用一个静态值填充数组从起始索引到结束索引的所有元素。另请参见 Array.prototype.fill()

TypedArray.prototype.filter()

使用此数组中所有提供过滤函数返回 true 的元素创建一个新数组。另请参见 Array.prototype.filter()

TypedArray.prototype.find()

返回数组中满足提供的测试函数的第一个 element,如果没有找到合适的元素则返回 undefined。另请参见 Array.prototype.find()

TypedArray.prototype.findIndex()

返回数组中满足所提供测试函数的第一个索引值,如果未找到合适的元素则返回 -1。另请参见 Array.prototype.findIndex()

TypedArray.prototype.findLast()

返回数组中满足提供的测试函数的最后一个元素的值,如果没有找到合适的元素则返回 undefined。另请参见 Array.prototype.findLast()

TypedArray.prototype.findLastIndex()

返回数组中满足提供的测试函数的最后一个元素的索引,如果未找到合适的元素则返回 -1。另请参见 Array.prototype.findLastIndex()

TypedArray.prototype.forEach()

对数组中的每个元素调用一个函数。另请参见 Array.prototype.forEach()

TypedArray.prototype.includes()

确定类型化数组是否包含某个元素,返回 truefalse。另请参见 Array.prototype.includes()

TypedArray.prototype.indexOf()

返回数组中等于指定值的元素的第一个(最小)索引,如果没有找到则返回 -1。另请参见 Array.prototype.indexOf()

TypedArray.prototype.join()

将数组的所有元素连接成一个字符串。另请参见 Array.prototype.join()

TypedArray.prototype.keys()

返回一个新的数组迭代器,其中包含数组中每个索引的键。另请参见 Array.prototype.keys()

TypedArray.prototype.lastIndexOf()

返回数组中等于指定值的元素的最后一个(最大)索引,如果没有找到则返回 -1。另请参见 Array.prototype.lastIndexOf()

TypedArray.prototype.map()

通过对数组中的每个元素调用提供的函数的结果创建一个新数组。另请参见 Array.prototype.map()

TypedArray.prototype.reduce()

对累加器和数组的每个值(从左到右)应用一个函数,以将其简化为单个值。另请参见 Array.prototype.reduce()

TypedArray.prototype.reduceRight()

对累加器和数组的每个值(从右到左)应用一个函数,以将其简化为单个值。另请参见 Array.prototype.reduceRight()

TypedArray.prototype.reverse()

反转数组元素的顺序——第一个变成最后一个,最后一个变成第一个。另请参见 Array.prototype.reverse()

TypedArray.prototype.set()

将多个值存储在类型化数组中,从指定的数组读取输入值。

TypedArray.prototype.slice()

提取数组的一部分并返回一个新数组。另请参见 Array.prototype.slice()

TypedArray.prototype.some()

如果数组中存在一个满足所提供测试函数的元素,则返回 true。否则,返回 false。另请参见 Array.prototype.some()

TypedArray.prototype.sort()

对数组元素进行原地排序并返回数组。另请参见 Array.prototype.sort()

TypedArray.prototype.subarray()

从给定的起始和结束元素索引返回一个新的 TypedArray

TypedArray.prototype.toLocaleString()

返回表示数组及其元素的本地化字符串。另请参见 Array.prototype.toLocaleString()

TypedArray.prototype.toReversed()

返回一个元素顺序反转的新数组,而不修改原始数组。

TypedArray.prototype.toSorted()

返回一个元素按升序排序的新数组,而不修改原始数组。

TypedArray.prototype.toString()

返回表示数组及其元素的字符串。另请参见 Array.prototype.toString()

TypedArray.prototype.values()

返回一个新的“数组迭代器”对象,其中包含数组中每个索引的值。另请参见 Array.prototype.values()

TypedArray.prototype.with()

返回一个新数组,其中给定索引处的元素替换为给定值,而不修改原始数组。

TypedArray.prototype[Symbol.iterator]()

返回一个新的“数组迭代器”对象,其中包含数组中每个索引的值。

示例

属性访问

你可以使用标准的数组索引语法(即使用方括号表示法)引用数组中的元素。但是,在类型化数组上获取或设置索引属性不会在原型链中搜索此属性,即使索引超出范围。索引属性将查询 ArrayBuffer,并且永远不会查看对象属性。你仍然可以使用命名属性,就像所有对象一样。

js
// Setting and getting using standard array syntax
const int16 = new Int16Array(2);
int16[0] = 42;
console.log(int16[0]); // 42

// Indexed properties on prototypes are not consulted (Fx 25)
Int8Array.prototype[20] = "foo";
new Int8Array(32)[20]; // 0
// even when out of bound
Int8Array.prototype[20] = "foo";
new Int8Array(8)[20]; // undefined
// or with negative integers
Int8Array.prototype[-1] = "foo";
new Int8Array(8)[-1]; // undefined

// Named properties are allowed, though (Fx 30)
Int8Array.prototype.foo = "bar";
new Int8Array(32).foo; // "bar"

不能冻结

非空 TypedArray 不能被冻结,因为它们的底层 ArrayBuffer 可能通过缓冲区的另一个 TypedArray 视图被修改。这意味着对象永远不会真正被冻结。

js
const i8 = Int8Array.of(1, 2, 3);
Object.freeze(i8);
// TypeError: Cannot freeze array buffer views with elements

ByteOffset 必须对齐

TypedArray 构造为 ArrayBuffer 的视图时,byteOffset 参数必须与其元素大小对齐;换句话说,偏移量必须是 BYTES_PER_ELEMENT 的倍数。

js
const i32 = new Int32Array(new ArrayBuffer(4), 1);
// RangeError: start offset of Int32Array should be a multiple of 4
js
const i32 = new Int32Array(new ArrayBuffer(4), 0);

ByteLength 必须对齐

byteOffset 参数一样,传递给 TypedArray 构造函数的 ArrayBufferbyteLength 属性必须是构造函数的 BYTES_PER_ELEMENT 的倍数。

js
const i32 = new Int32Array(new ArrayBuffer(3));
// RangeError: byte length of Int32Array should be a multiple of 4
js
const i32 = new Int32Array(new ArrayBuffer(4));

规范

规范
ECMAScript® 2026 语言规范
# sec-typedarray-objects

浏览器兼容性

另见