ArrayBuffers are fixed length buffer of bytes.
The bytes in an ArrayBuffer are only accessible through a DataView
(for heterogenous data异构数据) or one of the typed arrays (for homogeneous data同类数据): Float32Array
, Float64Array
, Int8Array
, Int16Array
, Int32Array
, Uint8Array
,Uint8ClampedArray
, Uint16Array
, Uint32Array
.
Multiple DataView and typed arrays can be applied to one ArrayBuffer and changes to one view can be seen in the others immediately.
Constructors
new ArrayBuffer(byteLength : Number) : ArrayBuffer
Allocates a new ArrayBuffer
of the specified length where each byte starts as 0
.
var buffer = new ArrayBuffer(12); var dataView = new DataView(buffer); var int8View = new Int8Array(buffer); dataView.setInt32(0, 0x1234ABCD); console.log(dataView.getInt32(0).toString(16)); //1234abcd console.log(dataView.getInt8(0).toString(16)); //12 console.log(int8View[0].toString(16));//12
Instance Properties
The length of this
in bytes.
var buffer = new ArrayBuffer(12); console.log(buffer.byteLength);//12
Instance Methods
slice(beginByte : Number, [endByte : Number]) : ArrayBuffer
Creates a new ArrayBuffer with a copy of the bytes of this
between beginByte
(inclusive) and endByte
(exclusive). If endByte
is not specified, this.byteLength
is used. Changes to this
do not affect the copy returned by slice
.
var buffer = new ArrayBuffer(12); var x = new Int32Array(buffer); x[1] = 1234; var slice = buffer.slice(4); var y = new Int32Array(slice); console.log(x[1]); //1234 console.log(y[0]);//1234 x[1] = 6789; console.log(x[1]); //6789 console.log(y[0]);//1234
ArrayBuffer Methods
isView(value : Object) : Boolean
Returns true
if value
is an ArrayBufferView.
console.log(ArrayBuffer.isView(new Int32Array()));//true console.log(ArrayBuffer.isView(new Float64Array()));//true console.log(ArrayBuffer.isView(new Array()));//false
类型化数组就是累数组对象,它和 常规数组的区别是:
1.类型化数组中的元素都是数字,使用构造函数在创建类型化数组的时候决定了数组中的数组(有符号或者无符号整数或者浮点数)的类型和大小(以位为单位)
2.类型化数组有固定的长度
3.在创建类型化数组的时候,数组中的元素总是默认初始化为0.
可以使用以下构造函数来创建8种类型化数组
构造函数 | 数字类型 |
Int8Array() | 有符号字节 |
Unit8Array() | 无符号字节 |
Int16Array() | 有符号16位短整数 |
Unit16Array() | 无符号16位短整数 |
Int32Array() | 有符号32位整数 |
Unit32Array() | 无符号32位整数 |
Float32Array | 32位浮点数值 |
Float64Array() | 64位浮点数值:JavaScript中的常规数字 |
在创建一个类型化数组的时候,可以传递数组大小给构造函数,或者传递一个数组或者类型化数组用于初始化数组元素。一旦创建了类型化数组,皆可以像操作其他类型数组对象那样,通过常规的中括号表示法来对数组元素进行读写操作。
var bytes=new Unit8Array(1024);//1kb字节 for(var i=0;i<bytes.length;i++) //循环数组中的每个元素 bytes[i]=i & 0xFF; //设置为所用的低8位值 var copy=new Unit8Array(bytes); //创建数组的副本 var ints=new Int32Array([0,1,2,3]);//包含这4个int值的类型化数组
虽然现代JS语言实现对数组进行优化,使得数组操作已非常高效,但是类型化数组在执行时间内核内存使用上都要更高效。
下面的函数用于计算出比指定数值小的最大素数。
它使用了埃拉托色尼筛选算法,该算法要求使用一个大数组来存储哪些数字是素数,哪些是合数。
由于每个数组元素只要使用一位信息,因此这里使用Int8Array要比使用常规的JS数组更有效。
function sieve(n){ var a=new Int8Array(n+1); //如果x是合数,则a[x]为1 var max=Math.floor(Math.sqrt(n));//因数不能比它大 var p=2;//2是第二个素数 while(p<=max){ //对于小于max的合数 for(var i=2*p;i<=n;i+=p)//将p的倍数都标记为合数 a[i]=1; while(a[++p]) //下一个未标记的索引值是素数 } while(a[n]) n--; //反向循环找到最大素数 return n;//将它返回 }
如果当其中的Int8Array()构造函数替换成传统的Array()构造函数,sieve()函数依然可用,但是处理过程中可能需要2-3倍事件,而且需要更多的内存来存储大的参数n的值。
当处理图形相关的数字或数学相关的数字的时候,类型化数组也很有用:
var matrix=new Float64Array(9); //一个3*3的矩阵 var 3dPoint=new Int16Array(3); //3D空间中的一点 var rgba=new Unit8Array(4);//一个4字节的RGBA像素值 var sudoku=new Unit8Array(81);//一个9*9的数独版
使用js的中括号表示法可以获取和设置类型化数组的单个元素。然而,类型化数组自己还定义了一些用于设置和获取整个数组内容的方法,其中set()方法用于将一个常规或者类型化数组复制到一个类型化数组中:
var bytes=new Unit8Array(1024); //1kb缓冲区 var pattern=new Unit8Array([0,1,2,3]); //一个4个字节的数组 bytes.set(pattern);//将他们赋值到另一个数组的开始 bytes.set(pattern,4);//在另一个偏移量处再次开始复制他们 bytes.set([0,1,2,3,4],8);//或直接从一个常规数组复制值
类数组还有个sbuarray()方法,调用该方法返回部分数组内容:
var ints=new Int16Array([0,1,2,3,,4,5,6,7,8,9]); //10个短整数 var last3=int.subarray(ints.length-3,ints.length);//最后三个 last3[0];//=>7 等效ints[7];
要注意的是subarray()方法不会创建数值的副本,它只是直接返回原数组的其中一部分内容:
ints[9]=-1//改变原数组中的元素值,然后。。。 lasts[2] //-1;同时也改变了子数组中的元素值
subarray()方法返回了当前数组的一个新视图,这一事实,说明了类型化数组中某些重要概念,他们都是基于字节块的视图,称作为一个ArrayBuffer。每个类型化数组都有与基本缓冲区相关的三个属性:
last3.buffer; //返回一个ArrayBuffer对象 last3.buffer==ints.buffer;//true 两者都是同一个缓冲区上的视图 last3.byteOffset //14 此视图从基本缓冲区的第14个字节开始 last3.bytelength;//6 该视图是6字节(3个16位整数)
ArrayBuffer对象自身只有一个返回它长度的属性:
lats.byteLength;//6 此时图长度为6 lats.buffer.byteLength;//20 但是基本缓区域的长度是20
ArrayBuffer只是不透明的字节快,可以通过类型化数组获取这些字节,但是ArrayBuffer自己并不是一个类型化数组。然而,要注意的是:可以像对任意JavaScript对象那样,使用谁在数组索引来操作ArrayBuffer。但是,这样做并不能赋予访问缓冲区自己的权限:
var bytes=new Unit8Array(8); //分配8个字节 bytes[0]=1 //把第一个字节设置成1 bytes.buffer[0]; //undefined 缓冲区没有索引值0 bytes.buffer[1]=255; //试着错误地设置缓冲区中的字节 bytes.buffer[1]; //255:这只设置一个常规的JS属性 bytes[1]; //0 上面这行代码并没有设置字节
可以直接使用ArrayBuffer()构造函数来创建一个ArrayBUffer,有了ArrayBUffer对下岗后,可以在该缓冲上创建任意数量的类型化数组视图
var buf=new ArrayBuffer(1024*1024); //1MB var asbytes=new Unit8Array(buf); //视为字节 var asints=new Int32Array(buf); //视为32位有符号整数 var lastk=new Unit8Array(buf,1023*1024); //视最后1kb为字节 var ints2=new Int32Array(buf,1024,256); //视第二个1kb为256个整数
类型化数组允许将同样的字节序列看成8位,16位,32位或者64位的数据块。 这里提到了“字节顺序”:字节组织成更长的字的顺序。