JavaScript中的ArrayBuffer详细介绍


Posted in Javascript onDecember 08, 2014

相信每一个 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 控制台可以看到:

JavaScript中的ArrayBuffer详细介绍

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] 并没有变化。

除了上面的方式,我们还可以通过其他方式来创建一个数据化数组:

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.log(x.getInt8(0)); // 22

console.log(x.getFloat32(1)); // 3.1415927410125732

如果感兴趣,可以移步http://www.javascripture.com/DataView,作详细了解。

XHR2 中的 ArrayBuffer

ArrayBuffer 的应用特别广泛,无论是 WebSocket、WebAudio 还是 Ajax等等,前端方面只要是处理大数据或者想提高数据处理性能,那一定是少不了 ArrayBuffer 。

XHR2 并不是什么新东西,可能你用到了相关的特性,却不知这就是 XHR2 的内容。最主要的一个东西就是 xhr.responseType,他的作用是设置响应的数据格式,可选参数有:"text"、"arraybuffer"、"blob"或"document"。请注意,设置(或忽略)xhr.responseType = '' 会默认将响应设为"text"。这里存在一个这样的对应关系:

请求            响应

text            DOMString

arraybuffer     ArrayBuffer

blob            Blob

document        Document

举个栗子:

var xhr = new XMLHttpRequest();

xhr.open('GET', '/path/to/image.png', true);

xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {

    // this.response == uInt8Array.buffer

    var uInt8Array = new Uint8Array(this.response); 

};
xhr.send();

我们在 xhr.responseType 中设置了属性为 arraybuffer,那么在拿到的数据中就可以用数据化数组来接受啦!

小结

本文主要介绍了 Array 在堆栈模型中的存放方式,也详细描述了 ArrayBuffer 这个原始缓冲区的二进制数据类型,在 web 开发中,数据以及数据的储存是一个重要的部分,希望引起注意!

本文叙述上可能存在错误,请多多斧正!

Javascript 相关文章推荐
javascript之解决IE下不渲染的bug
Jun 29 Javascript
js如何判断用户是否是用微信浏览器
Jun 05 Javascript
jQuery中关于ScrollableGridPlugin.js(固定表头)插件的使用逐步解析
Jul 17 Javascript
JS实现的4种数字千位符格式化方法分享
Mar 02 Javascript
JavaScript将字符串转换为整数的方法
Apr 14 Javascript
js实现简单的验证码
Dec 25 Javascript
基于javascript简单实现对身份证校验
Jan 25 Javascript
老司机带你解读jQuery插件开发流程
May 16 Javascript
浅述Javascript的外部对象
Dec 07 Javascript
vue 优化CDN加速的方法示例
Sep 19 Javascript
vue计算属性get和set用法示例
Feb 08 Javascript
Vue安装浏览器开发工具的步骤详解
May 12 Javascript
JS实现仿京东淘宝竖排二级导航
Dec 08 #Javascript
js继承call()和apply()方法总结
Dec 08 #Javascript
ANGULARJS中用NG-BIND指令实现单向绑定的例子
Dec 08 #Javascript
详解Javascript动态操作CSS
Dec 08 #Javascript
jquery.ajax之beforeSend方法使用介绍
Dec 08 #Javascript
实例讲解JQuery中this和$(this)区别
Dec 08 #Javascript
Jquery实现由下向上展开效果的例子
Dec 08 #Javascript
You might like
表单复选框向PHP传输数据的代码
2007/11/13 PHP
php 魔术方法使用说明
2009/10/20 PHP
解析dedeCMS验证码的实现代码
2013/06/07 PHP
PHP生成json和xml类型接口数据格式
2015/05/17 PHP
php动态函数调用方法
2015/05/21 PHP
php等比例缩放图片及剪切图片代码分享
2016/02/13 PHP
php实现产品加入购物车功能(1)
2020/07/23 PHP
javscript对象原型的一些看法
2010/09/19 Javascript
jquery库文件略庞大用纯js替换jquery的方法
2014/08/12 Javascript
Javascript中实现trim()函数的两种方法
2015/02/04 Javascript
JavaScript函数使用的基本教程
2015/06/04 Javascript
jquery结婚电子请柬特效源码分享
2015/08/21 Javascript
jquery实现无刷新验证码的简单实例
2016/05/19 Javascript
前端js弹出框组件使用方法
2020/08/24 Javascript
通过构造函数实例化对象的方法
2017/06/28 Javascript
阿里大于短信验证码node koa2的实现代码(最新)
2017/09/07 Javascript
Vue使用axios出现options请求方法
2019/05/30 Javascript
解决Layui当中的导航条动态添加后渲染失败的问题
2019/09/25 Javascript
node.js中stream流中可读流和可写流的实现与使用方法实例分析
2020/02/13 Javascript
VUE 实现element upload上传图片到阿里云
2020/08/12 Javascript
[50:38]DOTA2-DPC中国联赛 正赛 Phoenix vs CDEC BO3 第二场 3月7日
2021/03/11 DOTA
神经网络python源码分享
2017/12/15 Python
详解用Python处理HTML转义字符的5种方式
2017/12/27 Python
Python3数据库操作包pymysql的操作方法
2018/07/16 Python
python定位xpath 节点位置的方法
2019/08/27 Python
使用OpenCV实现仿射变换—旋转功能
2019/08/29 Python
Python栈的实现方法示例【列表、单链表】
2020/02/22 Python
Python读写Excel表格的方法
2021/03/02 Python
详解前端HTML5几种存储方式的总结
2016/12/27 HTML / CSS
奥地利顶级内衣丝袜品牌英国站:Wolford英国
2016/08/29 全球购物
乔丹名人堂演讲稿
2014/05/24 职场文书
公司市场部岗位职责
2015/04/15 职场文书
2015年教师节感言
2015/08/03 职场文书
mysql字符串截取函数小结
2021/04/05 MySQL
MySQL 存储过程的优缺点分析
2021/05/20 MySQL
jupyter notebook保存文件默认路径更改方法汇总(亲测可以)
2021/06/09 Python