Typed Arrays 是神马?

本文摘自 勾三股四 更早时期的 不老歌 博客。

在越来越多的W3C规范中见到TypedArrays和arrayBuffer这两个名词了,由于实际开发中还用不到,每次读到,就跳过去了。

当然这是不对滴……

今天,我们就来讨论一下这个JavaScript typed arrays




简介

首先,这个东东可以看做是对字符串格式的扩展,也可以看做是比字符串更好的描述二进制内容的数据类型。我们都知道,平时用记事本打开一个二进制文件,往往会看到一些稀奇古怪的字符、间歇的空格空行等等。这是因为二进制文件中每一个“字符”单位的数据都是无意义的,这不想文本文件那样,每个字符单位的数据可以独立查看和理解。所以,我们在处理二进制数据的时候,用字符串是很困难的,能用到的恐怕就只有类似

for (var i = 0; i < str.length; i++) {
console.log(str.charCodeAt(i));
}
的操作,才有可能让我们进行二进制级别的数据操作。

我们今天要介绍的TypedArray比这样处理方便得多。


原理

TypedArray的大概原理就是以charCode数组的形式,把一个二进制文件进行分解和体现。而数字进制有8、16、32、64这么几种。


接口介绍

这里一共有2个独立的接口和1个系列的接口,独立的接口就是ArrayBuffer和ArrayBufferView,系列接口就是TypedArray系列,包括下面几种接口:

* Int8Array 1B
* Uint8Array 1B
* Uint8ClampedArray 1B
* Int16Array 2B
* Uint16Array 2B
* Int32Array 4B
* Uint32Array 4B
* Float32Array 4B
* Float64Array 8B

ArrayBuffer是用来记录数组形式的二进制数据的,主要有两个特性/方法:byteLength和slice(begin, end),用法和FileAPI中的Blob的接口相对应,基本一样。

ArrayBufferView则是用来可视化展示数据的一个基本接口,它包含一个ArrayBuffer对象,其特性名为buffer,另外有两个特性可以决定数据展示的范围:byteOffset和byteLength。

最后,TypedArray则是由ArrayBufferView继承而来,除了具有buffer、byteOffset、byteLength之外,还具有以下特性/方法:
const BYTES_PER_ELEMENT // 取决于具体的单位字节数

readonly length; // 长度

getter get(index); // 数组取值
setter set(index, value); // 数组赋值

void set(array[, offset]); // 设置数据
TypedArray subarray(begin[, end]); // 截取其中一部分



举个简单的例子

我们试着读取一下百度的favicon,打开http://www.baidu.com/,然后在命令行里敲入下面的代码:
var a = new XMLHttpRequest;
a.open('GET', 'http://www.baidu.com/favicon.ico');
a.responseType = 'arraybuffer';
a.send();
这样a.response就会得到一个ArrayBuffer对象,对象的数据内容正代表了站点图标的二进制数据。然后我们继续运行
var b = new Int16Array(a.response);
这样就得到了一份16进制格式的数据。我们将其在命令行输出,这时就会看到:
Int16Array
0: 0
1: 1
2: 1
3: 4112
4: 16
5: 1
6: 4
7: 296
8: 0
9: 22
10: 0
11: 40
12: 0
13: 16
14: 0
15: 32
16: 0
17: 1
18: 4
19: 0
20: 0
21: 128
22: 0
23: 0
24: 0
25: 0
26: 0
27: 0
28: 0
29: 0
30: 0
31: 0
32: 0
33: 0
34: 128
35: -32768
36: 0
37: -32768
38: 128
39: 128
40: 0
41: 128
42: 128
43: -32640
44: 0
45: -32640
46: 128
47: -16192
48: 192
49: 0
50: 255
51: -256
52: 0
53: -256
54: 255
55: 255
56: 0
57: 255
58: 255
59: -1
60: 0
61: -1
62: 255
63: -13108
64: -13108
65: -13108
66: -13108
67: -49
68: -1
69: -1
70: -769
71: -1841
72: -14388
73: -13188
74: -881
75: -817
76: -13108
77: -13108
78: -817
79: -817
80: -13108
81: -13108
82: -817
83: -1841
84: -13108
85: -13108
86: -881
87: -49
88: -13172
89: -14132
90: -769
91: -29489
92: -13176
93: -30516
94: -824
95: -13105
96: -29489
97: -824
98: -820
99: -13105
100: -49
101: -1793
102: -824
103: -29489
104: -14200
105: -14088
106: -769
107: -49
108: -13060
109: -13060
110: -769
111: -49
112: -13060
113: -13060
114: -769
115: -49
116: -14088
117: -28673
118: -769
119: -49
120: -1
121: -1
122: -769
123: -13108
124: -13108
125: -13108
126: -13108
127: 0
128: 0
129: 0
130: 0
131: 0
132: 0
133: 0
134: 0
135: 0
136: 0
137: 0
138: 0
139: 0
140: 0
141: 0
142: 0
143: 0
144: 0
145: 0
146: 0
147: 0
148: 0
149: 0
150: 0
151: 0
152: 0
153: 0
154: 0
155: 0
156: 0
157: 0
158: 0
buffer: ArrayBuffer
byteLength: 318
byteOffset: 0
length: 159
__proto__: Int16Array

这正是站点图标的数据,数据非常可视化,非常友好。


总结

TypedArray的好处是,略显枯燥晦涩的位操作,可以摇身一变,变成我们熟悉的数学计算,一个比较好理解的事情,就是用js实现zip压缩算法。感兴趣的可以移步到zip.js去看看他们的实现。

其实我这里还等于顺带介绍了XMLHttpRequest Level 2,新增的接口我刚才的例子中也提到了一部分。其它新增的接口还有请求与发送更丰富的数据格式、ajax请求可以显示进度(onprogress)等等,这里不做展开介绍了,感兴趣的可以自行移步学习。

以上

向本文提出修改或勘误建议