二进制数组的由来
主要是为了提高浏览器与显卡之间的通信效率,由二进制数据代替传统的文本。
二进制数组主要有三个对象:
- ArrayBuffer
- TypedArray
- DataView
ArrayBuffer对象
ArrayBuffer是一个构造函数,参数是一个数字,代表索取多少个字节的内存。例如:
var buffer = new ArrayBuffer(12);
代表生成12个字节的内存区域。
注意:ArrayBuffer对象本身并不能直接对生成的内存区域进行读写(除了slice方法),需要借助视图TypedArray和DataView来对其进行读写。
三个方法:
- 实例方法byteLength,返回生成内存的字节大小
- 实例方法slice,这个方法和数组类似,就是生成一段新的内存,并填充拷贝的内容
- 静态方法isView,是否是视图
TypedArray的用法
这种类型的视图总共有9种构造函数:
- Int8Array 8位 有符号 一个字节 整数
- Uint8Array 8位 无符号 一个字节 整数
- Uint8ClampedArray 8位 无符号 一个字节 整数
- Int16Array 16位 有符号 两个字节 整数
- Uint16Array 16位 无符号 两个字节 整数
- Int32Array 32位 有符号 四个字节 整数
- Uint32Array 32位 无符号 四个字节 整数
- Float32Array 32位 四个字节 浮点数
- Float64Array 64位 八个字节 浮点数
用法1:
new TypedArray(buf, start, length)
- buf ArrayBuffer对象
- start开始的位置,默认是0
- length 字节的长度 相对于这种数据类型的长度
用法2:
new TypedArray(length)
直接传入一个长度,生成一段内存区域
用法3:
new TypedArray(typedArray对象)
demo2中x和y视图并没有共享内存,如果想共享视图可以这样(传入实例的buffer属性):
用法4:
new TypedArray(普通的数组)
demo4中操作typedArray不会使aa发生变化,说明它们没有共用同一段内存。
TypedArray的数值
二进制数组采用小端字节序,数组前面的元素的位相对较低,越往后越高,比如demo5中32这个元素就没有后面0的元素位高,转化成16进制应该是0x0000000000000020,如果采用16位或者32位视图,再对应将其划分。
小端字节序:低位在前,高位在后;
大端字节序:高位在前,低位在后;
TypedArray的数值溢出
什么是溢出呢?看下图:
我们创建了一个Uint8Array视图,它每一个元素的最大值是255(8位),最小值是0,当给定的数值不在这个区间内时,就会发生溢出!从demo6中我们给第一个元素赋值5000,但显示的却是136,这种现象就叫做溢出。
那么溢出的规则是什么?经过我的摸索得出了几条规律!
无符号(先利用Uint8Array说明)
Uint8Array最大值255(max),最小值0(min),区间长度256(L),给其一个元素赋值m,最终显示的值是n(例子见demo7)
//无符号最小值都是0 if(m >= min){ //正向溢出 n = m%L } if (m < min) { //负向溢出,m是负数 n = L + m%L }
有符合(先利用Int8Array说明)
Int8Array最大值127(max),最小值-128(min),区间长度256(L),给其一个元素赋值m,最终显示的值是n(例子见demo8)
余数y = m%L //正向溢出(m是正数) if (y <= max) { n = y } if (y > max) { n = y - L } //负向溢出(此时y,min都是负数) if (y >= min) { n = y } if (y < min) { n = L + y }
DataView对象
DataView对象和TypedArray对象最大的区别是可以自定义大端字节序还是小端字节序!
用法:
var buf = new ArrayBuffer(n); var dv = new DataView(buf, 字节起始位置, 长度); //查看demo6
8个get方法:
- getInt8:读取1个字节,返回一个8位整数。
- getUint8:读取1个字节,返回一个无符号的8位整数。
- getInt16:读取2个字节,返回一个16位整数。
- getUint16:读取2个字节,返回一个无符号的16位整数。
- getInt32:读取4个字节,返回一个32位整数。
- getUint32:读取4个字节,返回一个无符号的32位整数。
- getFloat32:读取4个字节,返回一个32位浮点数。
- getFloat64:读取8个字节,返回一个64位浮点数。
//使用样例 dv.getXX(第几个字节,大端字节序(false)/小端字节序(true))
8个set方法:
- setInt8:写入1个字节的8位整数。
- setUint8:写入1个字节的8位无符号整数。
- setInt16:写入2个字节的16位整数。
- setUint16:写入2个字节的16位无符号整数。
- setInt32:写入4个字节的32位整数。
- setUint32:写入4个字节的32位无符号整数。
- setFloat32:写入4个字节的32位浮点数。
- setFloat64:写入8个字节的64位浮点数。
//使用样例 dv.setXX(第几个字节,数据, 大端字节序(false)/小端字节序(true))
总结
其实二进制数组在平时工作中并不常用,甚至不常见,不过还是有必要了解一下的!因为它是buffer的基础,所以在研究buffer之前先了解一下!因为根据我的测试,自己摸索出了一个通用的规则,帮助大家理解,大家也可以帮我验证,大家有想法的也可以留言给我补充!
喜欢我的文章就关注我吧,有问题可以发表评论,我们一起学习,共同成长!
本文暂时没有评论,来添加一个吧(●'◡'●)