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等主流浏览器逐渐提供对它的全面支持和可预见的性能优化,它将发挥越来越重要的作用。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。