JS对象数组,js的类数组

  JS对象数组,js的类数组

  我在Chrome的最新动态中提到了类型化数组(Typed Array)的概念,可能很多人都很陌生,那么它是什么,有什么用呢?

  以前的问题

  Web应用变得越来越强大,比如音视频处理和WebSocket。毫无疑问,如果Javascript能够快速方便地操作原始二进制数据,那将是相当有用的。在过去,我们必须将原始数据视为一个字符串,并使用charCodeAt方法从数据缓冲区读取字节。

  但是这种方法需要对数据进行多次转换(特别是当二进制数据不是字节格式数据时,比如32位整数或者浮点数),所以非常慢,容易出错。

  Javascript需要一种机制来更有效地访问原始二进制数据,这就产生了类型数组。

  定义

  实际上,除了Javascript,类型数组在许多其他语言中也是可用的。这是一个只有一种变量类型的数组。例如,float类型的数组将只包含浮点数,不能混合字符串和浮点数。此外,类型数组在初始化后不能更改大小。看起来是普通的Javascript数组,但是数据格式一致,类型相同(比如声音或者像素缓冲区数据)。

  有关阵列的规格,请参见此处。这个规范本质上定义了一个arrayBuffer类型,相当于普通的定长二进制缓冲区。我们不是直接访问和操作arrayBuffer的内容,而是需要类型数组来创建arrayBuffer的视图(从技术上讲,类型数组与arrayBuffer是等价的,因为本质上是一样的)。例如,要访问作为缓冲区的32位有符号整数数组,需要创建Int32Array类型的数组以指向arrayBuffer。

  多个类型数组视图可以指向同一个arrayBuffer,具有不同的类型、长度和位移。例如,下面的代码:

  上述代码中变量的数据结构如下。

  变量的数据结构

  类型包括以下类型:

  Type目前实际上是作为WebGL的一部分实现的(也和File API有关),但是在任何地方都可以使用。

  我们来谈谈类型数组的优点和用途。

  优势

  1.完美的表现

  所有与类型数组相关的文档中提到的重要一点是,类型数组比传统数组快得多,性能非常好。因为类型数组实际上是作为一个固定的内存块来访问的,所以传统常见的Javascript数组使用哈希查找的方法(因为元素长度是不确定的)。

  下面是一个简单的测试结果。在Firefox4 Beta1版本中,我们比较了普通数组和float 32数组在操作1亿个元素时每次操作所花费的时间。本次测试运行在Win7 64位、4G内存、英特尔双核1.3G CPU的平台上。我们运行这个测试8次,使用最慢的时间。需要指出的是,写一个普通的Javascript数组往往需要10秒以上,会导致脚本对话框变慢。

  下面我们有一个普通数组、类型数组(arrayBuffer)和imageData之间的性能比较,可以看到arrayBuffer会快很多。

  性能优异的阵列缓冲器

  其实在类型数组之前,Javascript也支持二进制字节数组,也就是imageData。ImageData是在Canvas元素的2D上下文中定义的数据类型。ImageData是在画布2D中调用getImageData或createImageData方法时创建的。imageData的data属性是一个字节数组,实际大小是图像的宽度*高度的四倍(因为每个像素有R、G、B、A四个通道)。我们之前在文章《用HTML5创建超酷图像灰度渐变效果》中使用了imageData。

  从图表数据来看,在多个浏览器中创建的imageData和arrayBuffer的性能远高于普通数组(数据源)。但是,有一个问题,后面会提到。

  可想而知,type array由于其优异的性能,可以广泛应用于Javascript图像和视频的处理和压缩,还有一些需要复杂运算的场景,比如MD5计算,从而更加快速高效地完成功能。例如,我们首先将imageData转换为类型数组,以换取更快的执行速度,如下面的代码所示:

  另一方面,由于类型数组可以显著提高HTML5 Canvas 2D Web App的性能,因此该功能对于使用HTML5创建网页游戏的开发人员来说将非常重要。

  这里有两个使用类型数组的例子。

  第一个是Energy2D的演示,用来比较普通数组和类型数组的性能。可以自己体会。

  Energy2D演示

  第二个例子是用type array、FileAPI和Web Workers实现的SHA1在线计算器,性能相当优秀。有了type array的支持,Javascript可以越来越快地执行SHA1、MD5等复杂运算。

  阵列支持的在线SHA1计算器

  2.二元支持

  上面提到的类型数组最重要的特点就是支持二进制数据。事实上,HTMl5的许多API现在都涉及音频和视频以及实时通信,这些功能往往依赖于二进制文件格式,如MP3音频、MP4视频和PNG图像。二进制格式对于减少带宽、提高性能以及在现有文件格式之间进行转换非常重要。

  类型使Web应用程序能够使用各种二进制文件格式,并直接操作文件的二进制内容,如从现有媒体文件中提取数据。

  在IE10上已经提供了对类型数组的支持(支持WebGL对于微软来说其实是一件很纠结的事情)。我们可以看看微软提供的二进制文件检测器的例子:

  在这个例子中,我们可以获得音乐文件的ID3头、视频文件的原始字节数据和附加文件的格式。其核心代码如下:

  这个代码实现了页面文件的二进制格式输出。

  特定应用

  下面是一个使用type array在画布图像和二进制数据之间进行转换,然后通过WebSocket发送的例子。作者提到“当我实现二进制WebSocket示例时,我学到了很多关于Javascript类型数组以及如何将对象转换成二进制数据的知识。我写了一个获取画布图像数据的例子,通过二进制WebSocket连接发送。WebSocket服务器获取图像数据,然后发送给所有连接的客户端(御姐:这让我想起了国外一个非常流行的应用draw something——最近——你可以画出我的猜想,我们可以通过这种方式实现一个类似的WebApp),然后客户端将画布数据还原成PNG图像。以这种方式发送图像数据比base64编码效率更高(数据小33%,更有利于序列化和存储)。”

  创造历史的应用程序-你画,我猜。

  WebSocket支持二进制数据的传输。对于WebSocket服务器来说,使用二进制数据比UTF-8更简单,但在浏览器支持方面仍然存在一些问题。

  在示例中,将画布数据转换为二进制格式的代码如下:

  将二进制数据恢复到映像的代码如下。请注意,我们不能直接从arrayBuffer中获取数据并放入Canvas。

  Adobe官网上有类似的完整例子:《Real Time Data Exchange in HTML5 with WebSocket》。你可以看到用数组类型发送图片的代码如下:

  问题

  理论上,类型数组的性能无疑比普通数组更快。但根据文章《现代浏览器里类型数组的性能》中的评测,可以看出type array在某些操作和某些浏览器中的性能较低。另外,imageData和ArrayBuffer的性能在同一个浏览器中有不同的表现。这种现象令人困惑,因为imageData和ArrayBuffer其实是为性能敏感函数而生的,理论上可以提供更快的读写速度。这很有可能是目前浏览器厂商对二进制数组优化不够造成的。希望以后浏览器对类型数组有更好的支持。

  在某些操作和浏览器下,类型数组的性能较低。

  摘要

  随着HTML5 Canvas、WebSocket等新功能的出现,WebApp可以做的事情越来越多,同时Web App对性能的要求也越来越高。Javascript类型数组就是在这种情况下应运而生的。随着IE、Chrome、Opera等主流浏览器逐渐提供对它的全面支持和可预见的性能优化,它将发挥越来越重要的作用。

JS对象数组,js的类数组