JavaScript中的ArrayBuffer详细介绍
相信每⼀个 javascript 学习者,都会去了解 JS 的各种基本数据类型,数组就是数据的组合,这是⼀个很基本也⼗分简单的概念,他的内容没多少,学好它也不是件难事情。但是本⽂着重要介绍的并不是我们往常看到的 Array,⽽是 ArrayBuffer。
我写的很多东西都是因为要完成某些特定的功能⽽刻意总结的,可以算是备忘,本⽂也是如此!前段时间⼀直在研究 Web Audio API 以及语⾳通信相关的知识,内容侧重于⾳频流在 AudioContext 各个节点之间的流动情况,⽽现在要摸清楚⾳频到流底是个什么样的数据格式,所以对 ArrayBuffer 的研究就显得格外重要了。
Array 在内存中的堆栈模型
Array 的获取
Javascript 中如何产⽣ Array:
复制代码代码如下:
[element0, element1, ..., elementN]
new Array(element0, element1, ..., elementN)
new Array(arrayLength)
直接定义,或者通过构造函数创建⼀个 Array,当然也可以使⽤其他的⼿段:
复制代码代码如下:
"array".split("");
"array".match(/a|r/g);
等等,⽅式有很多。但是 Array 内部是个什么样的结构,恐怕很多⼈还不是很清楚。
堆栈模型
在数组中我们可以放很多不同数据类型的数据,如:
复制代码代码如下:
var arr = [21, "李靖", new Date(), function(){}, , null];
上⾯这个数组中⼀次放⼊了数字、字符串、对象、函数、undefined 和 null,对于上⾯的数据接⼝我们可以具象的描述下:
复制代码代码如下:
栈
+---------+ 堆
| 21 | +-------------------+
+---------+ | |
| "李靖" | | |
+---------+ | +--------+ |
| [refer] |----------->| Object | |
+---------+ | +--------+ |
| [refer] |----------------->+--------+ |
+---------+ | |function| |
|undefined| | +--------+ |
+---------+ | |
| null | +-------------------+
+---------+ Created By Barret Lee
JavaScript 的数据类型分为两种,⼀种是值类型,⼀种是引⽤类型,常见的引⽤类型有 Object 和 Array,数组的储存模型中,如果是诸如 Number、String 之类的值类型数据会被直接压⼊栈中,⽽引⽤类型只会压⼊对该值的⼀个索引,⽤ C 语⾔的概念来解释就是只保存了数据的指针,这些数据是储存在堆中的某块区间中。栈堆并不是独⽴的,栈也可以在堆中存放。
好了,对 Array 的说明就到这⾥,下⾯具体说说 ArrayBuffer 的相关知识。
ArrayBuffer
web 是个啥玩意⼉,web 要讨论的最基本问题是什么?我觉得有两点,⼀个是数据,⼀个是数据传输,
⾄于数据的展⽰,纷繁复杂,这个应该是 web 上层的东西。⽽本⽂要讨论的 ArrayBuffer 就是最基础的数据类型,甚⾄不能称之为数据类型,它是⼀个数据容易,需要通过其他⽅式来读写。
官⽅点的定义:
The ArrayBuffer is a data type that is used to represent a generic, fixed-length binary data buffer. You can't directly manipulate the contents of an ArrayBuffer; instead, you create an ArrayBufferView object which represents the buffer in a specific format, and use that to read and write the contents of the buffer.
表⽰⼆进制数据的原始缓冲区,该缓冲区⽤于存储各种类型化数组的数据。⽆法直接读取或写⼊ ArrayBuffer,但可根据需要将其传递到类型化数组或 DataView 对象来解释原始缓冲区。
他是⼀个⼆进制数据的原始缓冲区,虽然 JavaScript 是弱类型语⾔,但是他本⾝是对数据的类型和⼤⼩都有限制的,我们需要通过某种数据结构将缓冲区的内容有序的读取出来(写进去)。
原始缓冲区的创建
通过 ArrayBuffer 这个构造函数可以创建⼀个原始缓冲区:
复制代码代码如下:
var buffer = new ArrayBuffer(30);
从 chrome 控制台可以看到:
buffer 实例拥有⼀个 byteLength 的属性,⽤于获取 buffer 的 size,⼀个只有 IE11+ 以及 ios6+ ⽀持的 slice ⽅法,⽤于对buffer 长度进⾏截取操作。
复制代码代码如下:
ArrayBuffer slice(
unsigned long begin
unsigned long end Optional
);
可以测试这个 DEMO:
复制代码代码如下:
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]);
console.log(y[0]);
x[1] = 6789;
console.log(x[1]);
console.log(y[0]);
数据化数组
类型化数组类型表⽰可编制索引和操纵的 ArrayBuffer 对象的各种视图。所有数组类型的长度均固定。
复制代码代码如下:
名称⼤⼩(以字节为单位)描述
Int8Array 1 8 位⼆补码有符号整数
Uint8Array 1 8 位⽆符号整数
Int16Array 2 16 位⼆补码有符号整数
Uint16Array 2 16 位⽆符号整数
Int32Array 4 32 位⼆补码有符号整数
Uint32Array 4 32 位⽆符号整数
Float32Array 4 32 位 IEEE 浮点数
Float64Array 8 64 位 IEEE 浮点数
Int 就是整型,Uint 为⽆符号整形,Float 为浮点型,这些是 C 语⾔中的基本概念,我就不具体解释了。由于这些视图化结构都是⼤同⼩异,本⽂只对 Float32Array 类型作说明,读者可以举⼀反三。
Float32Array 跟 Array 是⼗分类似的,只不过他每⼀个元素都是都是⼀个 32位(4字节)的浮点型数据。Float32Array ⼀旦创建其⼤⼩不能再修改。
我们可以直接创建⼀个 Float32Array:
复制代码代码如下:
var x = new Float32Array(2);
x[0] = 17;
console.log(x[0]); // 17
console.log(x[1]); // 0
console.log(x.length); // 2
需要有这么⼀个概念,他依然是⼀个数组,只不过该数组中的每个元素都是 Float 32 位的数据类型,再如:
复制代码代码如下:
var x = new Float32Array([17, -45.3]);
console.log(x[0]); // 17
console.log(x[1]); // -45.29999923706055
console.log(x.length); // 2
我们把⼀个数组的值直接赋给了 x 这个 Float32Array 对象,那么在储存之前会将它转换成⼀个 32位浮点数。
由于该类数组的每个元素都是同⼀类型,所以在堆栈模型中,他们全部会被压⼊到栈之中,因此数据化数组都是值类型,他并不是引⽤类型!这个要引起注意,从下⾯的例⼦中也可以反映出来:
复制代码代码如下:
var x = new Float32Array([17, -45.3]);
var y = new Float32Array(x);
console.log(x[0]); // 17
console.log(x[1]); //-45.29999923706055
console.log(x.length); // 2
x[0] = -2;
console.log(y[0]); // 17, y的值没变
将 x 的值复制给 y,修改 x[0], y[0] 并没有变化。
除了上⾯的⽅式,我们还可以通过其他⽅式来创建⼀个数据化数组:
js的基本数据类型复制代码代码如下:
var buffer = new ArrayBuffer(12);
var x = new Float32Array(buffer, 0, 2);
var y = new Float32Array(buffer, 4, 1);
x[1] = 7;
console.log(y[0]); // 7
解释下这⾥为什么返回 7.
复制代码代码如下:
ArrayBuffer(12)
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0|1|2|3|4|5|6|7|8| | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
\ /
x (Float32Array)
offset:0
byteLength:4
length:2
ArrayBuffer(12)
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0|1|2|3|4|5|6|7|8| | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
\ /
y
Created By Barret Lee
看了上⾯的图解还有疑问么?我觉得我不⽤继续解释了。可以把 ArrayBuffer 的单位看成 1,⽽ Float32Array 的单位是 4. DataView对象
DataView 对象对数据的操作更加细致,不过我觉得没啥意思,上⾯提到的各种数据化数组已经可以基本满⾜应⽤了,所以这⾥就⼀笔带过,⼀个简单的⽰例:
复制代码代码如下:
var buffer = new ArrayBuffer(12);
var x = new DataView(buffer, 0);
x.setInt8(0, 22);
x.setFloat32(1, Math.PI);
console.Int8(0)); // 22
console.Float32(1)); // 3.1415927410125732
XHR2 中的 ArrayBuffer
ArrayBuffer 的应⽤特别⼴泛,⽆论是 WebSocket、WebAudio 还是 Ajax等等,前端⽅⾯只要是处理⼤数据或者想提⾼数据处理性能,那⼀定是少不了 ArrayBuffer 。
XHR2 并不是什么新东西,可能你⽤到了相关的特性,却不知这就是 XHR2 的内容。最主要的⼀个东西就是
复制代码代码如下:
请求响应
text DOMString
arraybuffer ArrayBuffer
blob Blob
document Document
举个栗⼦:
复制代码代码如下:
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
// sponse == uInt8Array.buffer
var uInt8Array = new sponse);
};
xhr.send();
我们在 sponseType 中设置了属性为 arraybuffer,那么在拿到的数据中就可以⽤数据化数组来接受啦!
⼩结
本⽂主要介绍了 Array 在堆栈模型中的存放⽅式,也详细描述了 ArrayBuffer 这个原始缓冲区的⼆进制数据类型,在 web 开发
中,数据以及数据的储存是⼀个重要的部分,希望引起注意!本⽂叙述上可能存在错误,请多多斧正!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论