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