JavaScript类型数组(JavaScript typed arrays)是一种类似数组的对象,它由ArrayBuffer、TypedArray、DataView三类对象构成,通过这些对象为JavaScript提供了访问二进制数据的能力。
1. 类型数组(二进制数组)
1.1 概述
在以往的Web应用中,JavaScript处理二进制数据,需要数据当作String并且使用charCodeAt()方法从数据缓冲区(buffer)中读取字节。在这种方式下,处理数据需要多次进行数据转换,不仅效率低而且容易出错。
随着Web应用变得日益强大,各种新功能,如:音/视频处理、通过WebSocket直接访问原始数据等。如果 JavaScript 能够快速而直接的处理原始数据这将会对我们很有帮助。
JavaScript typed arrays(类型数组)提供了一种更加高效的机制来访问和处理原始二进制数据。类型数组并不同于普通意义上的Array对象,在它上面调用Array.isArray()方法时会返回false。
1.2 缓存(Buffer)与视图(View):typed array架构
为了达到最大的灵活性和高效性, JavaScript 的typed array把实现分成了缓存(Buffer)和视图(View)。缓存是ArrayBuffer类的实现),是一个表示某数据片段的对象,它本身并没有格式可言,要访问它的数据应该使用一个视图。 视图提供了一个数据类型,起始数据偏移量,和其他一些元素,通过这些把数据转化成实际的数组类型。
二进制数组由以下对象组成:
ArrayBuffer
ArrayBuffer是一个用于表示二进制缓冲区(buffer)的对象,它并没有能力去访问和操作它自身的数据内容,要操作 ArrayBuffer中的数据,需要创建一个Typed array views或DataView来读写缓存区内容。
Typed array views
Typed array views是一组具有描述性的名字的不同类型的数组视图,如:Int8Array、Int32Array、Float32Array等。
DataView
DataView 提供了一些底层的API,通过这些API可以从ArrayBuffer中读/写数据。
2. ArrayBuffer对象
ArrayBuffer是缓存数组对象,是一种用于呈现通用、固定长度的二进制数据的类型。它是一段二进制的内存空间,并不能直接构造和填充ArrayBuffer内容,要读写其内容应该先创建一个TypedArray或DataView视图。
2.1 语法结构
new ArrayBuffer(length)
创建一个ArrayBuffer对象可以调用其构造函数,创建时可以传入一个表示要创建数组长度的参数。
参数:
length-要创建二进制数组的长度
返回值:
ArrayBuffer-指定长度二进制数组实例
2.2 ArrayBuffer使用示例
创建一个8位的二进制数组,再创建一个Int32Array类型数组来读写这个数组:
var buffer = new ArrayBuffer(8); var view = new Int32Array(buffer);
这样我们就创建了一个Int32类型的数组,通过这个数组我们可对二进制数组进行读写:
view[0]=1; view[0]; // 1
3. TypedArray视图对象
TypedArray对象是一个描述二进制缓存数据(ArrayBuffer)的类似数组的视图对象。TypedArray对象由一组子对象构成,我们可以根据Buffer类型的不同而建立不同类型的数据视图,每种类型的视图都可以从不同的索引位置开始为缓存建立内容视图。
3.1 语法结构
new TypedArray(length); new TypedArray(typedArray); new TypedArray(object); new TypedArray(buffer [, byteOffset [, length]]); where TypedArray() is one of: Int8Array(); Uint8Array(); Uint8ClampedArray(); Int16Array(); Uint16Array(); Int32Array(); Uint32Array(); Float32Array(); Float64Array();
TypedArray子类型的构造函数可以接受以三个参数:
ArrayBuffer-必须,底层的ArrayBuffer对象byteOffset-可选,开始的偏移量(默认为0)length-可选,视图中包含的数据数(默认为缓存的数据总数)
TypedArray对象并不是一个独立或全局对象,它由以下9种子对象类型组成,每种子类型都有其自己的构造函数:
Int8Array:8位有符号整数,长度1个字节。Uint8Array:8位无符号整数,长度1个字节。Uint8ClampedArray:8位无符号整数,长度1个字节,溢出处理不同。Int16Array:16位有符号整数,长度2字节。Uint16Array:16位无符号整数,长度2字节。Int32Array:32位有符号整数,长度4字节。Uint32Array:32位无符号整数,长度4字节。Float32Array:32位浮点数,长度4字节。Float64Array:64位浮点数,长度8字节。
3.2 使用示例
对于一个ArrayBuffer对象,我们可以根据其类型的不同而建立多个不同类型视图,这些视图都来自TypedArray的子类型。示例如下:
// Setting and getting using standard array syntax var 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"
4. DataView
DataView视图对象提供了一个更底层访问接口,通过这个接口我们可以读写多个ArrayBuffer,而且这些访问接口是与平台无关的格式类型。
4.1 语法结构
new DataView(buffer [, byteOffset [, length]])
DataView视图提供更多操作选项,用于ArrayBuffer的TypedArray对象中的子类型其更偏向于处理本机的二进制数据(如:网卡、声卡等二进制数据),而DataView更偏向于处理网络设备传来的数据,这个对象具有更多的可设置性。
DataView构造函数参数与TypedArray参数相同:
ArrayBuffer-必须,底层的ArrayBuffer对象byteOffset-可选,开始的偏移量(默认为0)length-可选,视图中包含的数据数(默认为缓存的数据总数)
4.2 DataView使用示例
DataView视图在初始化时并不需要指定数据类型,但它提供了一系列实例方法,通过这些方法可以设置写入的数据类型(如:setInt8()设置写入8位整型)或读取数据类型(如:getInt8()读取8位整型):
var buffer = new ArrayBuffer(16); var dv = new DataView(buffer, 0); dv.setInt16(1, 42); dv.getInt16(1); //42
