专业的编程技术博客社区

网站首页 > 博客文章 正文

JS操作内存?二进制数组了解一下(js操作二进制数据)

baijin 2024-08-16 11:41:13 博客文章 16 ℃ 0 评论

二进制数组的由来

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

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

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

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

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表