TypedArray
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
TypedArray 对象描述了底层 二进制数据缓冲区 的类似数组的视图。没有名为 TypedArray
的全局属性,也没有直接可见的 TypedArray
构造函数。相反,有许多不同的全局属性,其值是特定元素类型的类型化数组构造函数,如下所列。在接下来的几页中,你将找到可用于包含任何类型元素的任何类型化数组的常见属性和方法。
¥A TypedArray object describes an array-like view of an
underlying binary data buffer.
There is no global property named TypedArray
, nor is there a
directly visible TypedArray
constructor. Instead, there are a number of
different global properties, whose values are typed array constructors for specific
element types, listed below. On the following pages you will find common properties and
methods that can be used with any typed array containing elements of any type.
Try it
描述
¥Description
TypedArray
构造函数(通常称为 %TypedArray%
以指示其 "intrinsicness",因为它不对应于暴露给 JavaScript 程序的任何全局)充当所有 TypedArray
子类的公共超类。将 %TypedArray%
视为 "抽象类",为所有类型化数组子类提供实用方法的通用接口。这个构造函数没有直接暴露:没有全局 TypedArray
属性。它只能通过 Object.getPrototypeOf(Int8Array)
和类似的方式访问。
¥The TypedArray
constructor (often referred to as %TypedArray%
to indicate its "intrinsicness", since it does not correspond to any global exposed to a JavaScript program) serves as the common superclass of all TypedArray
subclasses. Think about %TypedArray%
as an "abstract class" providing a common interface of utility methods for all typed array subclasses. This constructor is not directly exposed: there is no global TypedArray
property. It is only accessible through Object.getPrototypeOf(Int8Array)
and similar.
创建 TypedArray
子类(例如 Int8Array
)的实例时,会在内存中内部创建一个数组缓冲区,或者,如果将 ArrayBuffer
对象作为构造函数参数给出,则使用 ArrayBuffer
来代替。缓冲区地址被保存为实例的内部属性,%TypedArray%.prototype
的所有方法都将基于该数组缓冲区地址设置和获取值。
¥When creating an instance of a TypedArray
subclass (e.g. Int8Array
), an array buffer is created internally in memory or, if an ArrayBuffer
object is given as constructor argument, that ArrayBuffer
is used instead. The buffer address is saved as an internal property of the instance and all the methods of %TypedArray%.prototype
will set and get values based on that array buffer address.
类型数组对象
¥TypedArray objects
类型 | 值范围 | 大小(以字节为单位) | 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 |
-65504 至 65504 |
2 | N/A |
Float32Array |
-3.4e38 至 3.4e38 |
4 | unrestricted float |
Float64Array |
-1.8e308 至 1.8e308 |
8 | unrestricted double |
BigInt64Array |
-263 至 263 - 1 | 8 | bigint |
BigUint64Array |
0 到 264 - 1 | 8 | bigint |
值编码和标准化
¥Value encoding and normalization
所有类型化数组都在 ArrayBuffer
上运行,你可以在其中观察每个元素的确切字节表示形式,因此如何将数字编码为二进制格式非常重要。
¥All typed arrays operate on ArrayBuffer
s, where you can observe the exact byte representation of each element, so how the numbers are encoded in binary format is significant.
- 无符号整数数组(
Uint8Array
、Uint16Array
、Uint32Array
和BigUint64Array
)直接以二进制形式存储数字。 - 有符号整数数组(
Int8Array
、Int16Array
、Int32Array
和BigInt64Array
)使用 二进制补码 存储数字。 - 浮点数组(
Float16Array
、Float32Array
和Float64Array
)使用 IEEE 754 浮点格式存储数字。Number
参考包含有关确切格式的更多信息。JavaScript 数字默认使用双精度浮点格式,与Float64Array
相同。Float32Array
使用 23 位(而不是 52 位)作为尾数,使用 8 位(而不是 11 位)作为指数。Float16Array
使用 10 位作为尾数,使用 5 位作为指数。请注意,规范要求所有NaN
值使用相同的位编码,但确切的位模式取决于实现。 Uint8ClampedArray
是一个特例。它像Uint8Array
一样以二进制形式存储数字,但是当你存储超出范围的数字时,它会通过数学值将数字限制在 0 到 255 的范围内,而不是截断最高有效位。
除 Int8Array
、Uint8Array
和 Uint8ClampedArray
之外的所有类型化数组都使用多个字节存储每个元素。这些字节可以从最高有效到最低有效(大端)或从最低有效到最高有效(小端)排序。请参阅 字节顺序 了解更多说明。类型化数组始终使用平台的原生字节顺序。如果要在写入和读取缓冲区时指定字节顺序,则应使用 DataView
。
¥All typed arrays except Int8Array
, Uint8Array
, and Uint8ClampedArray
store each element using multiple bytes. These bytes can either be ordered from most significant to least significant (big-endian) or from least significant to most significant (little-endian). See Endianness for more explanation. Typed arrays always use the platform's native byte order. If you want to specify the endianness when writing and reading from buffers, you should use a DataView
instead.
当写入这些类型化数组时,超出可表示范围的值将被标准化。
¥When writing to these typed arrays, values that are outside the representable range are normalized.
- 所有整数数组(
Uint8ClampedArray
除外)都使用 固定宽度数字转换,它首先截断数字的小数部分,然后取最低位。 Uint8ClampedArray
首先将数字限制在 0 到 255 的范围内(大于 255 的值变为 255,小于 0 的值变为 0)。然后,它将结果四舍五入(而不是取整)到最接近的整数,半到偶数;这意味着如果数字正好位于两个整数之间,则会四舍五入到最接近的偶数。例如,0.5
变为0
,1.5
变为2
,2.5
变为2
。Float16Array
和Float32Array
执行 "四舍五入到偶数",将 64 位浮点数转换为 32 位和 16 位。这与Math.fround()
和Math.f16round()
提供的算法相同。
查看可调整大小的缓冲区时的行为
¥Behavior when viewing a resizable buffer
当 TypedArray
作为 可调整大小的缓冲区 的视图创建时,调整底层缓冲区的大小将对 TypedArray
的大小产生不同的影响,具体取决于 TypedArray
是否构造为长度跟踪。
¥When a TypedArray
is created as a view of a resizable buffer, resizing the underlying buffer will have different effects on the size of the TypedArray
depending on whether the TypedArray
is constructed as length-tracking.
如果通过省略第三个参数或传递 undefined
创建没有特定大小的类型化数组,则类型化数组将成为长度跟踪,并且会在调整后者大小时自动调整大小以适合基础 buffer
:
¥If a typed array is created without a specific size by omitting the third parameter or passing undefined
, the typed array will become length-tracking, and will automatically resize to fit the underlying buffer
as the latter is resized:
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
:
¥If a typed array is created with a specific size using the third length
parameter, it won't resize to contain the buffer
as the latter is grown:
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。这是非长度跟踪类型化数组的长度可能改变的唯一情况。
¥When a buffer
is shrunk, the viewing typed array may become out of bounds, in which case the typed array's observed size will decrease to 0. This is the only case where a non-length-tracking typed array's length may change.
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
以使类型化数组回到边界内,则类型化数组的大小将恢复为其原始值。
¥If you then grow the buffer
again to bring the typed array back in bounds, the typed array's size will be restored to its original value.
buffer.resize(8);
console.log(float32.byteLength); // 8
console.log(float32.length); // 2
console.log(float32[0]); // 0 - back in bounds again!
如果缓冲区缩小到 byteOffset
之外,长度跟踪类型数组也会发生同样的情况。
¥The same can happen for length-tracking typed arrays as well, if the buffer is shrunk beyond the byteOffset
.
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
构造函数
¥Constructor
该对象无法直接实例化 - 尝试使用 new
构造它会抛出 TypeError
。
¥This object cannot be instantiated directly — attempting to construct it with new
throws a TypeError
.
new (Object.getPrototypeOf(Int8Array))();
// TypeError: Abstract class TypedArray not directly constructable
相反,你创建特定类型的类型化数组的实例,例如 Int8Array
或 BigInt64Array
。这些对象的构造函数都有一个通用的语法:
¥Instead, you create an instance of a typed array of a particular type, such as an Int8Array
or a BigInt64Array
. These objects all have a common syntax for their constructors:
new TypedArray()
new TypedArray(length)
new TypedArray(typedArray)
new TypedArray(object)
new TypedArray(buffer)
new TypedArray(buffer, byteOffset)
new TypedArray(buffer, byteOffset, length)
其中 TypedArray
是具体类型之一的构造函数。
¥Where TypedArray
is a constructor for one of the concrete types.
注意:所有
TypedArray
子类的构造函数只能用new
构造。尝试在没有new
的情况下调用一个会抛出TypeError
。¥Note: All
TypedArray
subclasses' constructors can only be constructed withnew
. Attempting to call one withoutnew
throws aTypeError
.
参数
¥Parameters
typedArray
-
当使用
TypedArray
子类的实例调用时,typedArray
被复制到新的类型化数组中。对于非 bigintTypedArray
构造函数,typedArray
参数只能是非 bigint 类型之一(例如Int32Array
)。同样,对于 bigintTypedArray
构造函数(BigInt64Array
或BigUint64Array
),typedArray
参数只能是 bigint 类型之一。typedArray
中的每个值在复制到新数组之前都会转换为构造函数的相应类型。新类型化数组的长度将与typedArray
参数的长度相同。 object
-
当使用不是
TypedArray
实例的对象调用时,将以与TypedArray.from()
方法相同的方式创建一个新的类型化数组。 length
Optional-
当使用非对象调用时,参数将被视为指定类型化数组长度的数字。在内存中创建一个内部数组缓冲区,大小为
length
乘以BYTES_PER_ELEMENT
字节,并用零填充。省略所有参数相当于使用0
作为length
。 buffer
,byteOffset
Optional,length
Optional-
当使用
ArrayBuffer
或SharedArrayBuffer
实例以及可选的byteOffset
和length
参数调用时,将创建一个新的类型化数组视图来查看指定的缓冲区。byteOffset
(以字节为单位)和length
(以元素数量为单位,每个占用BYTES_PER_ELEMENT
字节)参数指定类型化数组视图将公开的内存范围。如果两者都省略,则查看全部buffer
;如果仅省略length
,则查看从byteOffset
开始的buffer
的剩余部分。如果省略length
,类型化数组将变为 length-tracking。
例外情况
¥Exceptions
所有 TypeArray
子类构造函数都以相同的方式操作。他们都会抛出以下异常:
¥All TypeArray
subclass constructors operate in the same way. They would all throw the following exceptions:
TypeError
-
有下列情况之一的,抛出:
- 传递了
typedArray
,但它是 bigint 类型,而当前构造函数不是,反之亦然。 - 传递了
typedArray
,但它正在查看的缓冲区已分离,或者直接传递了分离的buffer
。
- 传递了
RangeError
-
有下列情况之一的,抛出:
- 新类型化数组的长度太大。
buffer
(如果未指定length
参数)或byteOffset
的长度不是新类型化数组元素大小的整数倍。byteOffset
不是有效的数组索引(0 到 253 - 1 之间的整数)。- 从缓冲区创建视图时,边界位于缓冲区之外。换句话说,
byteOffset + length * TypedArray.BYTES_PER_ELEMENT > buffer.byteLength
。
静态属性
¥Static properties
这些属性在 TypedArray
构造函数对象上定义,因此由所有 TypedArray
子类构造函数共享。
¥These properties are defined on the TypedArray
constructor object and are thus shared by all TypedArray
subclass constructors.
TypedArray[Symbol.species]
-
用于创建派生对象的构造函数。
所有 TypedArray
子类还具有以下静态属性:
¥All TypedArray
subclasses also have the following static properties:
TypedArray.BYTES_PER_ELEMENT
-
返回不同
TypedArray
对象的元素大小的数值。
静态方法
¥Static methods
这些方法在 TypedArray
构造函数对象上定义,因此由所有 TypedArray
子类构造函数共享。
¥These methods are defined on the TypedArray
constructor object and are thus shared by all TypedArray
subclass constructors.
TypedArray.from()
-
从类似数组或可迭代的对象创建一个新的
TypedArray
。另见Array.from()
。 TypedArray.of()
-
创建一个具有可变数量参数的新
TypedArray
。另见Array.of()
。
实例属性
¥Instance properties
这些属性在 TypedArray.prototype
上定义并由所有 TypedArray
子类实例共享。
¥These properties are defined on TypedArray.prototype
and shared by all TypedArray
subclass instances.
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
子类还具有以下实例属性:
¥All TypedArray
subclasses also have the following instance properties:
TypedArray.prototype.BYTES_PER_ELEMENT
-
返回不同
TypedArray
对象的元素大小的数值。
实例方法
¥Instance methods
这些方法在 TypedArray
原型对象上定义,因此由所有 TypedArray
子类实例共享。
¥These methods are defined on the TypedArray
prototype object and are thus shared by all TypedArray
subclass instances.
TypedArray.prototype.at()
-
获取一个整数值并返回该索引处的项目。此方法允许使用负整数,即从最后一项开始倒数。
TypedArray.prototype.copyWithin()
-
复制数组内的数组元素序列。另见
Array.prototype.copyWithin()
。 TypedArray.prototype.entries()
-
返回一个新的数组迭代器对象,其中包含数组中每个索引的键/值对。另见
Array.prototype.entries()
。 TypedArray.prototype.every()
-
测试数组中的所有元素是否通过函数提供的测试。另见
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()
-
确定类型化数组是否包含某个元素,根据情况返回
true
或false
。另见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
。另见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]()
-
返回一个新的数组迭代器对象,其中包含数组中每个索引的值。
示例
属性使用权
¥Property access
你可以使用标准数组索引语法(即使用括号表示法)引用数组中的元素。但是,在类型化数组上获取或设置索引属性不会在原型链中搜索该属性,即使索引超出范围也是如此。索引属性将参考 ArrayBuffer
并且永远不会查看对象属性。你仍然可以使用命名属性,就像使用所有对象一样。
¥You can reference elements in the array using standard array index syntax (that is,
using bracket notation). However, getting or setting indexed properties on typed arrays
will not search in the prototype chain for this property, even when the indices are out
of bound. Indexed properties will consult the ArrayBuffer
and will never
look at object properties. You can still use named properties, just like with all
objects.
// 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"
无法冷冻
¥Cannot be frozen
非空的 TypedArray
不能被冻结,因为它们的底层 ArrayBuffer
可能会通过缓冲区的另一个 TypedArray
视图发生突变。这意味着该对象永远不会真正被冻结。
¥TypedArray
s that aren't empty cannot be frozen, as their
underlying ArrayBuffer
could be mutated through another
TypedArray
view of the buffer. This would mean that the object
would never genuinely be frozen.
const i8 = Int8Array.of(1, 2, 3);
Object.freeze(i8);
// TypeError: Cannot freeze array buffer views with elements
ByteOffset 必须对齐
¥ByteOffset must be aligned
将 TypedArray
构造为 ArrayBuffer
的视图时,byteOffset
参数必须与其元素大小对齐;换句话说,偏移量必须是 BYTES_PER_ELEMENT
的倍数。
¥When constructing a TypedArray
as a view onto an
ArrayBuffer
, the byteOffset
argument must be aligned to its
element size; in other words, the offset must be a multiple of
BYTES_PER_ELEMENT
.
const i32 = new Int32Array(new ArrayBuffer(4), 1);
// RangeError: start offset of Int32Array should be a multiple of 4
const i32 = new Int32Array(new ArrayBuffer(4), 0);
字节长度必须对齐
¥ByteLength must be aligned
与 byteOffset
参数一样,传递给 TypedArray
构造函数的 ArrayBuffer
的 byteLength
属性必须是构造函数的 BYTES_PER_ELEMENT
的倍数。
¥Like the byteOffset
parameter, the byteLength
property of an
ArrayBuffer
passed to a TypedArray
's constructor
must be a multiple of the constructor's BYTES_PER_ELEMENT
.
const i32 = new Int32Array(new ArrayBuffer(3));
// RangeError: byte length of Int32Array should be a multiple of 4
const i32 = new Int32Array(new ArrayBuffer(4));
规范
Specification |
---|
ECMAScript Language Specification # sec-typedarray-objects |
浏览器兼容性
BCD tables only load in the browser