遇见Javascript类型数组
2012-04-02 10:43
309 查看
我在Chrome的最新动态里提到了Typed Arrays(Typed Array,类型数组)这个概念,可能对很多人来说非常陌生,那么它是什么,又有什么用途呢?
之前的问题
Web应用程序变得越来越强大,例如新增了音视频处理、WebSocket等多个功能特性。毫无疑问,如果Javascript能够快速方便的操作原始二进制数据会相当的有用。过去,我们必须要把原始数据当作字符串来处理,并且使用charCodeAt方法来从数据缓冲区中读取字节。
但是这种方法需要多次转换数据(尤其在二进制数据不是字节格式的数据时,例如32位整数或者浮点数),所以非常慢而且容易出错。
Javascript需要一种机制来更有效的访问原始的二进制数据,由此产生了类型数组。
定义
其实除了Javascript,类型数组在其他很多语言中也有。它是一种数组,只有一种变量的类型。例如,一个float类型的数组将只包含浮点数而不能混用字符串和浮点数。此外,一个类型数组在初始化后不能改变大小。它看起来形式和普通Javascript数组很像,但是数据格式是一致和同一类型的(例如声音或者像素点的缓冲数据)。
类型数组的规范参见这里。这个规范实质上定义了一种arrayBuffer类型,相当于一个普通的定长二进制缓冲区。我们不能直接访问和操作arrayBuffer的内容,而需要类型数组来创建arrayBuffer的视图(从技术上来说,类型数组等同于arrayBuffer,因为它们本质上是一样的)。例如,要访问32位有符号整数数组作为缓冲区,会创建一个Int32Array的类型数组来指向arrayBuffer。
多个类型数组视图可以指向同一个arrayBuffer,采用不同的类型、不同的长度以及不同的位移。例如下面的代码:
另外一方面,因为类型数组可以显著增加HTML5 Canvas 2D Web App的性能,所以这一特性对于使用HTML5来创建Web游戏的开发者会非常重要。
下面是两个使用类型数组的示例。
第一个是Energy2D的演示,用于对比普通数组和类型数组的性能,大家可以自行体验。
Energy2D演示
第二个示例是使用类型数组、FileAPI以及Web Workers实现的SHA1在线计算器,它的性能相当出色。正是在类型数组的支持下,Javascript执行SHA1、MD5这样复杂运算的速度变得越来越快。
类型数组支持的在线SHA1计算器
2、 二进制支持
上文曾经提到类型数组最主要的特点是支持二进制数据。的确,现在HTMl5的许多API涉及音视频和实时通信,这些功能经常依赖于二进制文件格式,例如MP3音频、MP4视频和PNG图像。二进制格式对于减少带宽,提高性能,以及与现有文件格式互相转换来说非常重要。
类型数组使得Web应用可以使用多种二进制文件格式和直接操作文件的二进制内容,例如从现有的媒体文件中提取数据。
在IE10上,已经提供了类型数组的支持(支持WebGL其实是微软非常纠结的事情)。我们可以看看微软所提供的二进制文件检测器的例子:
在这个示例里,我们可以获取音乐文件的ID3头,视频文件的原始字节数据,以及附加文件的格式。它的核心代码如下:
而把二进制数据还原为图像的代码如下,请注意我们不能直接从arrayBuffer获取数据直接放到Canvas中。
疑问
理论上来看,类型数组的性能毫无疑问比普通数组更快,但是根据《现代浏览器里类型数组的性能》一文中的评测,可以看到某些操作和某些浏览器下,类型数组的性能反而更低,另外imageData和ArrayBuffer的性能在同一浏览器中还有不同的表现。这个现象让人困惑,因为imageData和ArrayBuffer其实就是为了性能敏感的功能诞生的,理论上能够提供更快的读取和写入速度。这有极大可能是目前浏览器厂商对于二进制数组优化不足造成的。我希望浏览器未来对于类型数组能有更好的支持。
某些操作和浏览器下,类型数组性能反而更低
总结
随着HTML5 Canvas、WebSocket等新特性的出现,WebApp能做的事情越来越多,同时Web App对于性能要求也越来越高,Javascript类型数组正是在这种情况下应运而生的。随着IE、Chrome、Opera等主流浏览器逐步提供对它的全面支持,以及可预期的性能优化,它将会发挥越来越重要的作用。
之前的问题
Web应用程序变得越来越强大,例如新增了音视频处理、WebSocket等多个功能特性。毫无疑问,如果Javascript能够快速方便的操作原始二进制数据会相当的有用。过去,我们必须要把原始数据当作字符串来处理,并且使用charCodeAt方法来从数据缓冲区中读取字节。
但是这种方法需要多次转换数据(尤其在二进制数据不是字节格式的数据时,例如32位整数或者浮点数),所以非常慢而且容易出错。
Javascript需要一种机制来更有效的访问原始的二进制数据,由此产生了类型数组。
定义
其实除了Javascript,类型数组在其他很多语言中也有。它是一种数组,只有一种变量的类型。例如,一个float类型的数组将只包含浮点数而不能混用字符串和浮点数。此外,一个类型数组在初始化后不能改变大小。它看起来形式和普通Javascript数组很像,但是数据格式是一致和同一类型的(例如声音或者像素点的缓冲数据)。
类型数组的规范参见这里。这个规范实质上定义了一种arrayBuffer类型,相当于一个普通的定长二进制缓冲区。我们不能直接访问和操作arrayBuffer的内容,而需要类型数组来创建arrayBuffer的视图(从技术上来说,类型数组等同于arrayBuffer,因为它们本质上是一样的)。例如,要访问32位有符号整数数组作为缓冲区,会创建一个Int32Array的类型数组来指向arrayBuffer。
多个类型数组视图可以指向同一个arrayBuffer,采用不同的类型、不同的长度以及不同的位移。例如下面的代码:
var canvas = document.getElementById('canvas'); var canvasWidth = canvas.width; var canvasHeight = canvas.height; var ctx = canvas.getContext('2d'); var imageData = ctx.getImageData(0,0, canvasWidth, canvasHeight); var buf =new ArrayBuffer(imageData.data.length); var data =new Uint32Array(buf); for(var y =0; y < canvasHeight;++y){ for(var x =0; x < canvasWidth;++x){ var value = x * y &0xff; data[y * canvasWidth + x]= (255 <<24)| // alpha (value <<16)| // blue (value << 8)| // green value; // red } }
另外一方面,因为类型数组可以显著增加HTML5 Canvas 2D Web App的性能,所以这一特性对于使用HTML5来创建Web游戏的开发者会非常重要。
下面是两个使用类型数组的示例。
第一个是Energy2D的演示,用于对比普通数组和类型数组的性能,大家可以自行体验。
Energy2D演示
第二个示例是使用类型数组、FileAPI以及Web Workers实现的SHA1在线计算器,它的性能相当出色。正是在类型数组的支持下,Javascript执行SHA1、MD5这样复杂运算的速度变得越来越快。
类型数组支持的在线SHA1计算器
2、 二进制支持
上文曾经提到类型数组最主要的特点是支持二进制数据。的确,现在HTMl5的许多API涉及音视频和实时通信,这些功能经常依赖于二进制文件格式,例如MP3音频、MP4视频和PNG图像。二进制格式对于减少带宽,提高性能,以及与现有文件格式互相转换来说非常重要。
类型数组使得Web应用可以使用多种二进制文件格式和直接操作文件的二进制内容,例如从现有的媒体文件中提取数据。
在IE10上,已经提供了类型数组的支持(支持WebGL其实是微软非常纠结的事情)。我们可以看看微软所提供的二进制文件检测器的例子:
在这个示例里,我们可以获取音乐文件的ID3头,视频文件的原始字节数据,以及附加文件的格式。它的核心代码如下:
imagedata = context.getImageData(0, 0, imagewidth,imageheight); var canvaspixelarray = imagedata.data; var canvaspixellen = canvaspixelarray.length; var bytearray = new Uint8Array(canvaspixellen); for (var i=0;i<canvaspixellen;++i) { bytearray[i] = canvaspixelarray[i]; }
而把二进制数据还原为图像的代码如下,请注意我们不能直接从arrayBuffer获取数据直接放到Canvas中。
function sendphoto() { imagedata = context.getImageData(0, 0, imagewidth,imageheight); var canvaspixelarray = imagedata.data; var canvaspixellen = canvaspixelarray.length; var bytearray = new Uint8Array(canvaspixellen); for (var i=0;i<canvaspixellen;++i) { bytearray[i] = canvaspixelarray[i]; } connection.send(bytearray.buffer); context.fillStyle = '#ffffff'; context.fillRect(0, 0, imagewidth,imageheight); }
疑问
理论上来看,类型数组的性能毫无疑问比普通数组更快,但是根据《现代浏览器里类型数组的性能》一文中的评测,可以看到某些操作和某些浏览器下,类型数组的性能反而更低,另外imageData和ArrayBuffer的性能在同一浏览器中还有不同的表现。这个现象让人困惑,因为imageData和ArrayBuffer其实就是为了性能敏感的功能诞生的,理论上能够提供更快的读取和写入速度。这有极大可能是目前浏览器厂商对于二进制数组优化不足造成的。我希望浏览器未来对于类型数组能有更好的支持。
某些操作和浏览器下,类型数组性能反而更低
总结
随着HTML5 Canvas、WebSocket等新特性的出现,WebApp能做的事情越来越多,同时Web App对于性能要求也越来越高,Javascript类型数组正是在这种情况下应运而生的。随着IE、Chrome、Opera等主流浏览器逐步提供对它的全面支持,以及可预期的性能优化,它将会发挥越来越重要的作用。
相关文章推荐
- 遇见Javascript类型数组(Typed Array)
- 遇见Javascript类型数组(Typed Array)
- 遇见Javascript类型数组(Typed Array)
- 在JavaScript中实现类似Java中List<Map>类型的数组
- JavaScript中【数据类型】和【数组类型】的区别
- javascript封装判断全数据类型方法, toString方法, 对象的枚举(in, instanceof, hasOwnProperty的用法), arguments类数组属性
- javascript 类型数组读取二进制数据
- javascript的数组类型检测
- JavaScript——引用类型之Array篇(数组的基本操作)
- JavaScript中如何判断变量是数组、函数或是对象类型
- JavaScript中数组类型的常用操作方法以及属性
- JavaScript引用类型之Array数组的栈方法与队列方法
- Javascript类型系统[数组,对象,数据类型]
- javascript两个数组合并及判断数据类型的方法
- JavaScript引用类型:使用对象和创建并操作数组
- Effective JavaScript Item 46 优先使用数组而不是Object类型来表示有顺序的集合
- Javascript如何判断数据类型和数组类型
- Javascript数组类型检测:编写更强壮的isArray函数
- JavaScript对象、函数、数组、类型等(干货)
- JavaScript的“强类型数组”简介