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 相关文章推荐
form表单只提交数据而不进行页面跳转的解决方案
Sep 18 Javascript
技术男用来对妹子表白的百度首页
Jul 23 Javascript
jQuery 判断图片是否加载完成方法汇总
Aug 10 Javascript
AngularJS 让人爱不释手的八种功能
Mar 23 Javascript
JS实现“隐藏与显示”功能(多种方法)
Nov 24 Javascript
angular实现表单验证及提交功能
Feb 01 Javascript
Vue 2.0+Vue-router构建一个简单的单页应用(附源码)
Mar 14 Javascript
angular-cli修改端口号【angular2】
Apr 19 Javascript
理解Angular的providers给Http添加默认headers
Jul 04 Javascript
vue项目中api接口管理总结
Apr 20 Javascript
JavaScript实现动态添加、移除元素或属性的方法分析
Jan 03 Javascript
JS实现网站楼层导航效果代码实例
Jun 16 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版(2)
2006/10/09 PHP
PHP COOKIE设置为浏览器进程
2009/06/21 PHP
php中神奇的fastcgi_finish_request
2011/05/02 PHP
php模拟post上传图片实现代码
2016/06/24 PHP
PHP入门教程之图像处理技巧分析
2016/09/11 PHP
TP3.2框架分页相关实现方法分析
2020/06/03 PHP
基于jquery的回到页面顶部按钮
2011/06/27 Javascript
仿当当网淘宝网等主流电子商务网站商品分类导航菜单
2013/09/25 Javascript
JQuery打造省市下拉框联动效果
2014/05/18 Javascript
Windows 系统下安装和部署Egret的开发环境
2014/07/31 Javascript
checkbox 选中一个另一个checkbox也会选中的实现代码
2016/07/09 Javascript
jQuery实现的右下角广告窗体跟随效果示例
2016/09/16 Javascript
jQuery EasyUI Accordion可伸缩面板组件使用详解
2017/02/28 Javascript
实时监控input框,实现输入框与下拉框联动的实例
2018/01/23 Javascript
Angular2 父子组件通信方式的示例
2018/01/29 Javascript
使用express搭建一个简单的查询服务器的方法
2018/02/09 Javascript
JS中用EL表达式获取上下文参数值的方法
2018/03/28 Javascript
详解无限滚动插件vue-infinite-scroll源码解析
2019/05/12 Javascript
Vue 刷新当前路由的实现代码
2019/09/26 Javascript
Python 利用内置set函数对字符串和列表进行去重的方法
2018/06/29 Python
VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的方法详解
2019/07/01 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
2020/02/24 Python
python实现ssh及sftp功能(实例代码)
2020/03/16 Python
django 利用Q对象与F对象进行查询的实现
2020/05/15 Python
Python pickle模块常用方法代码实例
2020/10/10 Python
CSS3的常见transformation图形变化用法小结
2016/05/13 HTML / CSS
GafasWorld哥伦比亚:网上购买眼镜
2017/11/28 全球购物
Lookfantastic日本官网:英国知名护肤、化妆品和头发护理购物网站
2018/04/21 全球购物
澳大利亚音乐商店:Bava’s Music City
2019/05/05 全球购物
车工岗位职责
2013/11/26 职场文书
优秀的个人求职信范文
2014/05/09 职场文书
公司节能减排方案
2014/05/16 职场文书
会计求职信
2014/05/29 职场文书
离婚协议书样本
2015/01/26 职场文书
防卫过当辩护词
2015/05/21 职场文书
Python 中的Sympy详细使用
2021/08/07 Python