二进制数组操作的数组维度必须匹配_JS操作内存?二进制数组了解一下

二进制数组的由来

主要是为了提高浏览器与显卡之间的通信效率,由二进制数据代替传统的文本。

二进制数组主要有三个对象:

  • ArrayBuffer
  • TypedArray
  • DataView

ArrayBuffer对象

ArrayBuffer是一个构造函数,参数是一个数字,代表索取多少个字节的内存。例如:

var buffer = new ArrayBuffer(12);

代表生成12个字节的内存区域。

注意:ArrayBuffer对象本身并不能直接对生成的内存区域进行读写(除了slice方法),需要借助视图TypedArray和DataView来对其进行读写。

三个方法:

  • 实例方法byteLength,返回生成内存的字节大小
  • 实例方法slice,这个方法和数组类似,就是生成一段新的内存,并填充拷贝的内容
  • 静态方法isView,是否是视图
1aa9285f1fbb88d80dc833f6b2363f85.png

demo1

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对象)

e277fbd4b48c6dba0ff9ba15ac7f41fe.png

demo2

demo2中x和y视图并没有共享内存,如果想共享视图可以这样(传入实例的buffer属性):

120572b5adc50e5692a982197e3267fd.png

demo3

用法4:

new TypedArray(普通的数组)

ec357ab9c8244e6398a32ac0dae417ab.png

demo4

demo4中操作typedArray不会使aa发生变化,说明它们没有共用同一段内存。

TypedArray的数值

二进制数组采用小端字节序,数组前面的元素的位相对较低,越往后越高,比如demo5中32这个元素就没有后面0的元素位高,转化成16进制应该是0x0000000000000020,如果采用16位或者32位视图,再对应将其划分。

be6608a7335259fdc16caed530fdd7b0.png

demo5

小端字节序:低位在前,高位在后;

大端字节序:高位在前,低位在后;

TypedArray的数值溢出

什么是溢出呢?看下图:

31132c9205e72bfb7215be4bc5ad1ec9.png

demo6

我们创建了一个Uint8Array视图,它每一个元素的最大值是255(8位),最小值是0,当给定的数值不在这个区间内时,就会发生溢出!从demo6中我们给第一个元素赋值5000,但显示的却是136,这种现象就叫做溢出。

那么溢出的规则是什么?经过我的摸索得出了几条规律!

无符号(先利用Uint8Array说明)

Uint8Array最大值255(max),最小值0(min),区间长度256(L),给其一个元素赋值m,最终显示的值是n(例子见demo7)

//无符号最小值都是0if(m >= min){ //正向溢出 n = m%L } if (m < min) { //负向溢出,m是负数 n = L + m%L}
552c23ded7a966c9d2276b8f0a51432b.png

demo7

有符合(先利用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}
93912592b5d2c9c8b96f2591c9abb374.png

demo8

DataView对象

DataView对象和TypedArray对象最大的区别是可以自定义大端字节序还是小端字节序!

用法:

var buf = new ArrayBuffer(n);var dv = new DataView(buf, 字节起始位置, 长度);//查看demo6
adc8d763c7ef67d3aa780e084f8bbdd3.png

demo9

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之前先了解一下!因为根据我的测试,自己摸索出了一个通用的规则,帮助大家理解,大家也可以帮我验证,大家有想法的也可以留言给我补充!

喜欢我的文章就关注我吧,有问题可以发表评论,我们一起学习,共同成长!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值