其他分享
首页 > 其他分享> > JS的定型数组

JS的定型数组

作者:互联网

定型数组(typed array)是ECMAScript新增的结构,目的是提升向原生库传输数据的效率。实际上,JavaScript并没有”TypedArray“类型,它所指的其实是一种特殊的包含数值类型的数组。为理解如何使用定型数组,有必要先了解一下它的用途。

 

①ArrayBuffer

  Float32Array实际上是一种”视图“,可以允许JavaScript运行时访问一块名为ArrayBuffer的预分配内存。ArrayBuffer是所有定型数组及视图引用的基本单位。

注意:SharedArrayBuffer是ArrayBuffer的一个变体,可以无需复制就在执行上下文传递它。

 

ArrayBuffer()是一个普通的JavaScript构造函数,可用于在内存中分配特定数量的字节空间。

const buf=new ArrayBuffer(16);   //在内存中分配16字节
alert(buf.byteLength);    //16

ArrayBuffer一经创建就不能再调整大小,不过,可以使用slice()复制其全部或部分到一个新实例中:

const buf1=new ArrayBuffer(16);
const buf2=buf1.slice(4,12);
alert(buf2.byteLength);      //8

ArrayBuffer某种程度上类似于C++的malloc(),但也有几个明显的区别。

1)malloc()在分配失败时候会返回一个null指针。ArrayBuffer在分配失败时会抛出错误。

2)malloc()可以利用虚拟内存,因此最大可分配尺寸只受可寻址系统内存限制。ArrayBuffer分配的内存不能超过Number.Max_SAFE_INTEGER(2^53-1)字节

3)malloc()调用成功不会初始化实际的地址。声明ArrayBuffer,则会将所有二进制位初始化位0.

4)通过malloc()分配的堆内存除非调用free()或程序退出,否则系统不能再使用。而通过声明ArrayBuffer分配的堆内存可以被当成垃圾回收,不同手动释放。

不能仅通过对ArrayBuffer的引用就读取或写入其内容。要读取或写入ArrayBuffer,就必须通过视图。视图有不同的类型,但引用的都是ArrayBuffer中存储的二进制数据。

 

一、DataView

  第一种允许你读写ArrayBuffer的视图是DataView。这个视图专为文件I/O和网络I/O设计,其API支持对缓冲数据的高度控制,但相比于其他类型的视图性能也差一些。DataView对缓冲内容没有任何预设,也不能迭代。

  必须在对已有的ArrayBuffer读取或者写入时才能创建DataView实例。这个实例可以使用全部或者部分ArrayBuffer,且维护着对该缓冲实例的引用,以及视图在缓冲中开始的位置。

const buf=new ArrayBuffer(16);


//DataView默认使用整个ArrayBuffer
const fullDataView=new DataView(buf);
alert(fullDataView.byteOffset);   //0
alert(fullDataView.byteLength);  //16
alert(fullDataView.buffer===buf);       //true


//构造函数接收一个可选的字节偏移量和字节长度
//byteOffset=0表示视图从缓冲起点开始
//byteLength=8 限制视图为前8个字节

const firstHalfDataView=new DataView(buf,0,8);
alert(firstHalfDataView.byteOffset);     //0
alert(firstHalfDataView.byteLength);    //8
alert(firstHalfDataView.buffer===buf);   //true


//如果不指定,则DataView会使用剩余的缓冲
//byteOffset=8 表示视图从缓冲的第九个字节开始
// byteLength未指定,默认为剩余缓冲
const secondHalfDataView=new DataView(buf,8);
alert(secondHalfDataView.byteOffset);        //8
alert(secondHalfDataView.byteLength);        //8
alert(secondHalfDataView.buffer===buf);        //true
alert(secondHalfDataView.byteLength);        //8
alert(secondHalfDataView.buffer===buf); //true

要通过DataView读取缓冲,还需要几个组件。

首先是要读或写的字节偏移量。可以看成DataView中的某种”地址“。

DataView应该使用ElementType来实现JavaScript的Number类型到缓冲内二进制格式的转换。

最后是内存中值的字节序。默认为大端字节序。

(1)ElementType

DataView对存储在缓冲内的数据类型没有预设。它暴露的API强制开发者在读、写时指定一个ElementType,然后DataView就会忠实地为读、写而完成相应的转换。

ES6支持八种不同的ElementType(如下表)

ElementType 字节 说明 等价的C类型 值的范围
Int8 1 8位有符号整数 signed char -127~127
Uint8 1 8位无符号整数 unsigned char 0~255
Int16 2 16位有符号整数 short -32768~32767
Uint16 2 16位无符号整数 unsigned short 0~65535
Int32 4 32位有符号整数 int -2147483648~2147483647
Uint32 4 32位无符号整数 unsigned int 0~4294967295
Float32 4 32位IEEE-754浮点数 float -3.4e+38~+3.4e+38
Float 8 64位IEEE-754浮点数 double -1.7e+308~+1.7e+308

DataView为上表中的每种类型都暴露了get和set方法,这些方法使用byteOffset(字节偏移量)定位要读取或者写入值的位置。类型是可以互换使用的,如下例所示:

//在内存中分配两个字节并声明一个DataView

const buf=new ArrayBuffer(2);

const view=new DataView(buf);

 

//说明整个缓冲确实所有二进制位都是0

//检查第一个和第二个字符

alert(view.getInt8(0));  //0

alert(view.getInt8(1));  //0

//检查整个缓冲

alert(view.getInt(16));   //0

//将整个缓冲都设置为1

//255的二进制表示是11111111

view.setUint8(0,255);

//DataView会自动将数据转换为特定的ElementType

//255的十六进制表示为0xFF

view.setUint8(1,0xFF);

//现在、缓冲里都是1了

//如果把它当成二补数的有符号整数,则应该是-1

alert(view.getInt16(0));    //-1

标签:定型,缓冲,ArrayBuffer,DataView,视图,alert,数组,JS,buf
来源: https://www.cnblogs.com/jaetyn/p/16402105.html