ArrayBuffer是什么

154 阅读4分钟

历史

随着浏览器的流行,人们不限于在浏览器上运行简单的网页,而是想用它来运行复杂的3D应用程序,早期的WebGL就是这样诞生的。但是随着3D技术的发展,开发者发现JavaScript的数组与原生的数组之间存在差异(我的理解就是类似像JavaScript数组和C数组不匹配一样),需要做额外的处理来转换数组格式,所以造成了性能问题(3D技术嘛,性能开销很重要),为了解决这个问题,Mozilla提出了CanvasFloatArray,可以匹配原生数组,不用额外处理,后来CanvasFloatArray慢慢的演变成了Float32Array,也就是如今ArrayBuffer其中的一个视图类型。

2011年2月,ArrayBuffer被发布,ES6 将它们纳入了 ECMAScript 规格。

ArrayBuffer

ArrayBuffer通俗易懂来说就是javascript中用来处理二进制数据的接口,用数组的方式存储着二进制数据,所以也可以叫它二进制数组。

我们可以通过构造函数ArrayBuffer()在内存中分配特定数量的字节空间,其功能有点类似C++的malloc():

const buff=new ArrayBuffer(2)//在内存中分配两个字节的空间,一个字节8位

通过ArrayBuffer()构造函数分配的字节空间,默认所有位都是 0,并且一经分配就不可以再调整大小,不过我们可以通过ArrayBuffer实例的slice()方法复制全部或部分到一个新的实例中:

const buff=new ArrayBuffer(32)
const buff_other=buff.slice(4,12)//第一个参数是开始字节(包含),第二个参数是结束字节(不包含) [start,end)
console.log(buff_other.byteLength)//8

ArrayBuffer中保存的是原始的二进制数据,不能直接读取或者写入内容,如果要读取或者写入就必须通过视图,视图一般有两种:TypedArrayDataView,它们的作用是以指定格式解读二进制数据

TypedArray

TypedArray代表的不是一个构造函数,而是一组构造函数:Int8ArrayUint8ArrayUint8ClampedArrayInt16ArrayUint16ArrayInt32ArrayUint32ArrayFloat64Array以及前文提到的Float32Array,每一个构造函数都有与之等价的Web IDL 类型和C类型,可以省去额外的转换处理

每一个构造函数都以指定的格式解读数据,以Int32Array为例:

const buff=new ArrayBuffer(16)
const view=new Int32Array(buff)
for(let i=0;i<view.length;i++){
  view[i]=i*2
  console.log(view[i])// 0 2 4 6
}

Int32Array是32 位有符号整数,一个整数占据32位,一个字节是8位,也就是说一个整数占据4个字节,现在通过ArrayBuffer分配了16个字节,可以存放4个整数,循环遍历4次分别赋值,打印结果是0 2 4 6

DataView

与TypedArray不同,DataView表示一个构造函数,它接收一个ArrayBuffer对象参数,返回一个DataView实例:

const buff=new ArrayBuffer(16)
//默认使用整个ArrayBuffer
const view1=new DataView(buff)
//以buff从位置0开始8个长度的字节创建视图
const view2=new DataView(buff,0,8)
//截以buff从位置8开始8个长度的字节创建视图
const view3=new DataView(buff,8,8)

DataView通过不同的ElementType对ArrayBuffer对象进行不同格式的转换,ElementType有:Int8Uint8Int16Uint16Int32Uint32Float32Float64。每一个类型都暴露了一个get和set方法,这些方法使用betyOfffset(字节偏移量)定位要读取或写入值的位置:

const buff=new ArrayBuffer(2)

const view = new DataView(buff)
view.setUint8(0,255)//255的二进制是11111111
for(let i=0;i<view.byteLength;i++){
  console.log(view.getUint8(i))//255 0
}

总结

ArrayBuffer是JavaScript 中存储二进制数据的数组,有了它,大大增强了 JavaScript 处理二进制数据的能力。

我们可以通过ArrayBuffer()构造函数在内存中分配指定字节空间,并返回一个ArrayBuffer实例,这个实例上有一个属性byteLength和一个方法slicebyteLength可以访问当前ArrayBuffer对象的字节长度,slice可以复制实例的全部或部分内容并返回一个新实例。

创建的ArrayBuffer实例并不能直接进行读取和写入操作,想要进行读取和写入操作必须通过视图来完成,JavaScript中的视图主要有两种:DataView和TypeArray。DataView是一个构造函数,通过DataView构造函数创建的实例可以通过getElementTypesetElementType方法进行读取和写入操作。TypeArray是一组构造函数,通过不同构造函数创建返回的实例和普通数组相似,可以用数组的方式进行写入和读取。