二进制数组由三类对象组成:javascript
ArrayBuffer对象:表明原始的二进制数据。java
TypedArray视图:用来读写简单类型的二进制数据。数组
DataView视图:用来读写复杂类型的二进制数据。app
下面详细了解一下它们的用法:函数
它不能直接读写,只能经过(TypedArray
和DataView
)来读写。ui
ArrayBuffer
也是一个构造函数,能够分配一段能够存放数据的连续内存区域。编码
例如我想生成一段32字节的内存区域,每一个字节的值默认都是0,就能够这样建立:prototype
var buf = new ArrayBuffer(32);
byteLength
:是ArrayBuffer
实例的属性,返回所分配的内存区域的字节长度。code
var buffer = new ArrayBuffer(32); buffer.byteLength // 32
须要注意的是:若是你想分配一块比较大的内存区域,须要检查是否分配成功,由于可能没有那么多的连续空余内存。orm
if(buffer.byteLength === n){ //成功 }else{ //失败 }
slice
:有两个参数,第一个参数表示开始拷贝的字节序号(包含此字节),第二个参数表示截止拷贝的字节序号(不含此字节),若是省略第二个参数,则默认截止到原ArrayBuffer
对象的结尾。
slice
:是ArrayBuffer
实例的一个方法,容许将内存区域的一部分,拷贝生成一个新的ArrayBuffer
对象。
var buffer = new ArrayBuffer(8); var newBuffer = buffer.slice(0, 3); //拷贝`buffer`对象的前三个字节(从0到3前结束),生成一个新的ArrayBuffer对象:newBuffer
isView
:是ArrayBuffer
的一个静态方法,返回一个布尔值,表示参数是否为ArrayBuffer
的视图实例。这个方法大体至关于判断参数,是否为TypedArray
实例或DataView
实例。
var buffer = new ArrayBuffer(8); ArrayBuffer.isView(buffer) // false var v = new Int32Array(buffer); ArrayBuffer.isView(v) // true
TypedArray数组只提供9种固定的构造函数,用来生成相应类型的数组实例。
(1)TypedArray(buffer, byteOffset=0, length?)
视图的构造函数能够接受三个参数:
第一个参数(必需):视图对应的底层ArrayBuffer
对象。
第二个参数(可选):视图开始的字节序号,默认从0开始。
第三个参数(可选):视图包含的数据个数,默认直到本段内存区域结束。
// 建立一个8字节的ArrayBuffer var b = new ArrayBuffer(8); // 建立一个指向b的Int32视图,开始于字节0,直到缓冲区的末尾 var v1 = new Int32Array(b); // 建立一个指向b的Uint8视图,开始于字节2,直到缓冲区的末尾 var v2 = new Uint8Array(b, 2); // 建立一个指向b的Int16视图,开始于字节2,长度为2 var v3 = new Int16Array(b, 2, 2);
v1[0]是一个32位整数,指向字节0~字节3;v2[0]是一个8位无符号整数,指向字节2;v3[0]是一个16位整数,指向字节2~字节3。只要任何一个视图对内存有所修改,就会在另外两个视图上反应出来。
注:byteOffset必须与所要创建的数据类型一致,好比:带符号的16位整数须要两个字节,因此byteOffset参数必须可以被2整除
(2)TypedArray(length)
视图还能够不经过ArrayBuffer
对象,直接分配内存而生成。
var f64a = new Float64Array(8); //64字节 f64a[0] = 10; f64a[1] = 20; f64a[2] = f64a[0] + f64a[1]; // 30
(3)TypedArray(typedArray)
TypedArray
数组的构造函数,能够接受另外一个TypedArray
实例做为参数。
var typedArray = new Int8Array(new Uint8Array(4));
注:新数组会开辟一段新的内存存数据。
var x = new Int8Array([1, 1]); var y = new Int8Array(x); x[0] // 1 y[0] // 1 x[0] = 2; y[0] // 1 //基于同一段内存 var x = new Int8Array([1, 1]); var y = new Int8Array(x.buffer); x[0] // 1 y[0] // 1 x[0] = 2; y[0] // 2
(4)TypedArray(arrayLikeObject)
//普通数组生成TypedArray实例 var typedArray = new Uint8Array([1, 2, 3, 4]); //这时TypedArray视图会从新开辟内存,不会在原数组的内存上创建视图 //TypedArray数组转换回普通数组 var normalArray = Array.prototype.slice.call(typedArray);
须要注意的是:TypedArray数组除了没有concat方法以外,拥有普通数组全部的操做方法和属性
若是想要合并多个TypedArray数组,能够用下面这个函数。
function concatenate(resultConstructor, ...arrays) { let totalLength = 0; for (let arr of arrays) { totalLength += arr.length; } let result = new resultConstructor(totalLength); let offset = 0; for (let arr of arrays) { result.set(arr, offset); offset += arr.length; } return result; } concatenate(Uint8Array, Uint8Array.of(1, 2), Uint8Array.of(3, 4)) // Uint8Array [1, 2, 3, 4]
TypedArray数组也能够被遍历。
let ui8 = Uint8Array.of(0, 1, 2); for (let byte of ui8) { console.log(byte); } // 0 // 1 // 2
注:字符串的编码方法是肯定的,才能够相互转换。
// ArrayBuffer转为字符串,参数为ArrayBuffer对象 function ab2str(buf) { return String.fromCharCode.apply(null, new Uint16Array(buf)); } // 字符串转为ArrayBuffer对象,参数为字符串 function str2ab(str) { var buf = new ArrayBuffer(str.length * 2); // 每一个字符占用2个字节 var bufView = new Uint16Array(buf); for (var i = 0, strLen = str.length; i < strLen; i++) { bufView[i] = str.charCodeAt(i); } return buf; }
TypedArray.prototype.buffer
:返回整段内存区域对应的ArrayBuffer对象,属性为只读。
TypedArray.prototype.byteLength
:返回TypedArray数组占据的内存长度,单位为字节,属性为只读。
TypedArray.prototype.byteOffset
:返回TypedArray数组从底层ArrayBuffer对象的哪一个字节开始,属性为只读。
TypedArray.prototype.length
:TypedArray数组含有多少个成员。
TypedArray.prototype.set()
:用于复制数组(普通数组或TypedArray数组)。
TypedArray.prototype.subarray()
:对于TypedArray数组的一部分,再创建一个新的视图。
TypedArray.prototype.slice()
:返回一个指定位置的新的TypedArray实例。
TypedArray.of()
:用于将参数转为一个TypedArray实例。
TypedArray.from()
:返回一个基于这个结构的TypedArray实例。
var buffer = new ArrayBuffer(24); var idView = new Uint32Array(buffer, 0, 1); var usernameView = new Uint8Array(buffer, 4, 16); var amountDueView = new Float32Array(buffer, 20, 1);
上面代码将一个24字节长度的ArrayBuffer对象,分红三个部分:
字节0到字节3:1个32位无符号整数
字节4到字节19:16个8位整数
字节20到字节23:1个32位浮点数
DataView
实例有如下属性,含义与TypedArray
实例的同名方法相同。
DataView.prototype.buffer:返回对应的ArrayBuffer对象
DataView.prototype.byteLength:返回占据的内存字节长度
DataView.prototype.byteOffset:返回当前视图从对应的ArrayBuffer对象的哪一个字节开始
DataView
实例提供8个方法读取内存。
getInt8:读取1个字节,返回一个8位整数。
getUint8:读取1个字节,返回一个无符号的8位整数。
getInt16:读取2个字节,返回一个16位整数。
getUint16:读取2个字节,返回一个无符号的16位整数。
getInt32:读取4个字节,返回一个32位整数。
getUint32:读取4个字节,返回一个无符号的32位整数。
getFloat32:读取4个字节,返回一个32位浮点数。
getFloat64:读取8个字节,返回一个64位浮点数。
DataView
视图提供8个方法写入内存。
setInt8:写入1个字节的8位整数。
setUint8:写入1个字节的8位无符号整数。
setInt16:写入2个字节的16位整数。
setUint16:写入2个字节的16位无符号整数。
setInt32:写入4个字节的32位整数。
setUint32:写入4个字节的32位无符号整数。
setFloat32:写入4个字节的32位浮点数。
setFloat64:写入8个字节的64位浮点数。