本节是第四讲的第三十一小节,上一节我们为大家介绍了JavaScript的严格模式,本节将继续为大家介绍JavaScript类型数组。
JavaScript类型数组(Typed Arrays)
JavaScript类型化数组是一种类似数组的对象,并提供了一种用于访问原始二进制数据的机制。 正如你可能已经知道,Array 存储的对象能动态增多和减少,并且可以存储任何JavaScript值。JavaScript引擎会做一些内部优化,以便对数组的操作可以很快。然而,随着Web应用程序变得越来越强大,尤其一些新增加的功能例如:音频视频编辑,访问WebSockets的原始数据等,很明显有些时候如果使用JavaScript代码可以快速方便地通过类型化数组来操作原始的二进制数据将会非常有帮助。
但是,不要把类型化数组与正常数组混淆,因为在类型数组上调用 Array.isArray() 会返回false。此外,并不是所有可用于正常数组的方法都能被类型化数组所支持(如 push 和 pop)。
缓冲和视图:类型数组架构
为了达到最大的灵活性和效率,JavaScript 类型数组(Typed Arrays)将实现拆分为缓冲和视图两部分。一个缓冲(由 ArrayBuffer 对象实现)描述的是一个数据块。缓冲没有格式可言,并且不提供机制访问其内容。为了访问在缓冲对象中包含的内存,你需要使用视图。视图提供了上下文 — 即数据类型、起始偏移量和元素数 — 将数据转换为实际有类型的数组。
ArrayBuffer
ArrayBuffer 是一种数据类型,用来表示一个通用的、固定长度的二进制数据缓冲区。你不能直接操纵一个ArrayBuffer中的内容;你需要创建一个类型化数组的视图或一个描述缓冲数据格式的DataView,使用它们来读写缓冲区中的内容。
类型数组视图
类型化数组视图具有自描述性的名字和所有常用的数值类型像Int8,Uint32,Float64 等等。有一种特殊类型的数组Uint8ClampedArray。它仅操作0到255之间的数值。例如,这对于Canvas数据处理非常有用。
TypeValue RangeSize in bytes
Int8Array-128 to 1271
Uint8Array0 to 2551
Uint8ClampedArray0 to 2551
Int16Array-32768 to 327672
Uint16Array0 to 655352
Float32Array1.2×10-38 to 3.4×10384
Float64Array5.0×10-324 to 1.8×103088
BigInt64Array-263 to 263-18
BigUint64Array0 to 264-18
数据视图
DataView 是一种底层接口,它提供有可以操作缓冲区中任意数据的读写接口。这对操作不同类型数据的场景很有帮助,例如:类型化数组视图都是运行在本地字节序模式(参考 Endianness),可以通过使用 DataView 来控制字节序。默认是大端字节序(Big-endian),但可以调用读写接口改为小端字节序(Little-endian)。
使用类型数组的Web API
XMLHttpRequest 实例的 send() 方法现在使用支持类型化数组和 ArrayBuffer 对象作为参数。
ImageData.data
是一个 Uint8ClampedArray 对象,用来描述包含按照RGBA序列的颜色数据的一维数组,其值的范围在0到255(包含255)之间。
示例
首先,我们创建一个16字节固定长度的缓冲:
var buffer = new ArrayBuffer(16);
现在我们有了一段初始化为0的内存,目前还做不了什么太多操作。让我们确认一下数据的字节长度:
if (buffer.byteLength === 16) {
console.log("Yes, it's 16 bytes.");
} else {
console.log("Oh no, it's the wrong size!");
}
在实际开始操作这个缓冲之前,需要创建一个视图。我们将创建一个视图,此视图将把缓冲内的数据格式化为一个32位的有符号整数数组:
var int32View = new Int32Array(buffer);
现在我们可以像普通数组一样访问该数组中的元素:
for (var i = 0; i < int32View.length; i++) {
int32View[i] = i * 2;
}
该代码会将数组以0, 2, 4和6填充 (一共4个4字节元素,所以总长度为16字节)。
更有意思的是,你可以在同一数据上创建多个视图。例如:基于上文的代码,我们可以添加如下代码处理:
var int16View = new Int16Array(buffer);
for (var i = 0; i < int16View.length; i++) {
console.log("Entry " + i + ": " + int16View[i]);
}
这里我们创建了一个2字节整数视图,该视图共享上文的4字节整数视图的缓冲,然后以2字节整数打印出缓冲里的数据,这次我们会得到0, 0, 2, 0, 4, 0, 6, 0这样的输出。
那么,这样呢?
int16View[0] = 32;
console.log("Entry 0 in the 32-bit array is now " + int32View[0]);
这次的输出是"Entry 0 in the 32-bit array is now 32"。也就是,这2个数组都是同一数据的以不同格式展示出来的视图。你可以使用任何一种 view types 中的定义的视图。
转换为普通数组
在处理完一个类型化数组后,有时需要把它转为普通数组,以便可以可以像普通数据一种操作访问。可以调用 Array.from实现这种转换,如果 Array.from 不支持的话,也可以通过如下代码实现:
var typedArray = new Uint8Array([1, 2, 3, 4]),
normalArray.length === 4;
normalArray.constructor === Array;
以上内容部分摘自视频课程04网页游戏编程JavaScript-31类型数组,更多示例请参见网站示例。跟着张员外讲编程,学习更轻松,不花钱还能学习真本领。
领取专属 10元无门槛券
私享最新 技术干货