前两天看到一个新东西,就是 Typed Array(类型数组)。众所周知的 JS 的数组功能异常强大,不过强大的另一面就是其中的功能我们其实不需要那么多,性能上会差一点(弱类型语言都这样嘛……)。那么 HTML5 里由于对文件处理的需求大大增强,而大文件的二进制读取对性能要求更高一些,于是就出现了类型数组来解决这一问题。
创建类型数组
创建类型数组有三种方法:
1、直接建立定长的数组:
new TypedArray( [unsigned long length] );

2、通过 ArrayBuffer 来建立:
TypedArray( ArrayBuffer buffer [, unsigned long byteOffset] [, unsigned long length] )
ArrayBuffer 是一个定长的二进制缓存区,在打开文件的时候可以用 FileReader.readAsArrayBuffer 方法来读取文件内容至 ArrayBuffer 中,也可以用 new ArrayBuffer(length) 来直接生成一个 ArrayBuffer。用这种方法建立类型数组时,可以指定其偏移量(参数2)以及长度(参数3)。

3、通过原有的数组或类型数组来建立:
TypedArray( TypedArray / type[] array )
如果通过一个标准数组建立类型数组的话,新数组的每个元素都会自动进行类型转换,字符串会被自动无视,直接设为0。而数字如果超过范围的话,处理方式有一点差异,在后边再说~另外还有一个 subarray 方法,可以从原类型数组中截取一个子数组,可以指定开始和结束的位置。
TypedArray subarray( long begin [, long end] )
类型数组的种类
因为是类型数组……所有会有很多种不同类型的类型数组(我是在说绕口令么 0 0),于是见下表(我才不会说我是要跟贼寇炫耀我的编辑器可以生成华丽的表格):
类型
大小
描述
Web IDL 类型
等效的 C 类型
Int8Array
1
8位有符号整数
byte
signed char
Uint8Array
1
8位无符号整数
octet
unsigned char
Uint8ClampedArray
1
8位无符号整数(clamped)
octet
unsigned char
Int16Array
2
16位有符号整数
short
short
Uint16Array
2
16位无符号整数
unsigned short
unsigned short
Int32Array
4
32位有符号整数
long
int
Uint32Array
4
32位无符号整数
unsigned long
unsigned int
Float32Array
4
32位IEEE浮点数
unrestricted float
float
Float64Array
8
64位IEEE浮点数
unrestricted double
double

大部分不需要解释,大家都懂的……但是如上节所述,在数据超限的时候,不同类型(其实只有 Uint8ClampedArray 跟大家不一样)的处理方式是不一样的。其他所有的类型在数据超限时都是取模处理,比如 Uint8Array 如果赋值为 256,取模后就赋值为 0,同样的 -1 就处理为 255。而 Uint8ClampedArray 则是取与其最接近的合法值,因此 256 取为 255,-1则取为 0。这一类型的设置主要是方便 Canvas 的使用,因为在 ImageData 中存储图像数据的就是 Uint8ClampedArray 类型,而 Canvas 进行图像处理时遇到像素值超限显然是取最接近的合法值更为合理,所以 clamped 也只出现在 Uint8 上,够用就行~
数据处理
对类型数组进行取值和赋值就和普通数组一样直接用下标值就可以,不过 join,reverse 等等数组的方法都不能用了。同时由于是定长数组,push 和 pop 这些改变数组长度的方法也一概没有。另外,貌似还有一个 set 方法可以通过数组来赋值,不过遗憾的是我还没有搞明白这个方法是怎么用的……
void set( TypedArray / type[] array [, unsigned long offset] )
总结
表示懒的做测试……直接引用这篇文章中的一段:
我们知道Javascript中数字是64位浮点数。则对于一个二进制图片(图片每个像素点是以8位无符号整数存储的),如果要将其数据在Javascript数组中使用,相当于使用了图片8倍的内存来存储一个图片的数据,这显然是不科学的。而TypedArray能帮助我们只使用原来1/8的内存来存储图片数据。或者对于WebSocket,如果用base64进行传输也是一个花费较高的方式,转而使用二进制传送可能是更好的方式。

数据测试也可以直接看链接的那篇文章……就我个人现在的项目而言,把图片像素用类型数组进行保存后,读取解析并显示一幅737*467的IMG图像的时间可以从300毫秒出头减少到现在的230毫秒上下,提升还是相当明显的~

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注