對類型化數組(Typed Array)與ArrayBuffer的理解

類型化數組(Typed Array)也是HTML5中新引入的API。用一句話解釋類型化數組就是:它是JS操做二進制數據的接口。 衆所周知,直接操做二進制數據可使程序更爲高效, 儘管JS對常規數組作了不少優化(JS數組被實現爲對象形式),可是不得不認可JS數組的效率一直不高。好比在WebGL中的圖像數據傳輸, 若是使用原生的JS數組, 瀏覽器在與顯卡通訊時,必須將它轉換爲二進制形式,這一步較爲耗時。正是由於有大量二進制數據的操做需求,因此ArrayBuffer應運而生。在Canvas(可參考本人canvas筆記canvas的基本原理)中,使用getImageDate()方法所返回的ImageData對象就是一個類數組對象,HTML標準中稱其爲CanvasPixelArray,它除了在值的處理方式上與ArrayBuffer中視圖類型Unit8Array有點區別外,其餘都同樣(Unit8Array只能處理0-255的數字,而CanvasPixelArray能夠處理更多)編程

對於剛接觸類型化數組的概念看到這可能仍是雲裏霧裏,下面將逐一將我所理解的ArrayBuffer中的關鍵概念作個整理:canvas

視圖(View)

大多數資料中對於視圖都是一句帶過,好比這篇博客中(ArrayBuffer:類型化數組)對於視圖的解釋就是:segmentfault

ArrayBuffer做爲內存區域,能夠存放多種類型的數據。不一樣數據有不一樣的存儲方式,這就叫作「視圖」。數組

當我剛看到上面的解釋,仍是沒法體會「視圖」的含義,暫且把ArrayBuffer的概念放一邊, 想象一下,既然是操做二進制數據的接口,那麼該如何操做他們呢, 好比8位二進制數1是00000001,咱們確定不會使用原始的二進制編程,那麼當咱們操做這個1時,確定是以1的形式操做, 那麼這裏的1就是視圖(view)了, 視圖能夠理解爲方便理解的二進制數據。若是知道C語言,對於這個概念就不難把握了,好比C語言中的字符串實際是數字,那麼這裏的字符串也能夠理解爲「視圖」。其實這裏的視圖就是類型化數組。瀏覽器

ArrayBuffer的概念

ArrayBuffer是一段不透明的內存區域(所謂不透明,就是沒法直接操做的數據塊),單位是字節(Byte)也就是8位,它的byteLength屬性返回其內存大小。在JS中,經過構造函數的形式申明一段ArrayBuffer區域:網絡

var a = new ArrayBuffer(10)
a.byteLength // =>10

在這段內存區域上,可使用不一樣的視圖來建立任意數量的類型化數組, 這些類型化數組也能夠是重疊的。有八種不一樣的類型化數組(視圖),分別爲:架構

  • Int8Array:8位有符號整數,長度1個字節。函數

  • Uint8Array:8位無符號整數,長度1個字節。優化

  • Int16Array:16位有符號整數,長度2個字節。.net

  • Uint16Array:16位無符號整數,長度2個字節。

  • Int32Array:32位有符號整數,長度4個字節。

  • Uint32Array:32位無符號整數,長度4個字節。

  • Float32Array:32位浮點數,長度4個字節。

  • Float64Array:64位浮點數,長度8個字節。

這裏引用這篇博客中(JavaScript中的ArrayBuffer詳細介紹)的例子來解釋ArrayBuffer區域中出現的重疊(也叫複合視圖)現象:

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

原文中做者的解釋過於簡單。這裏的y[0]之因此爲7,是由於在buffer這段12個字節的內存區域中,申明來一個從0字節開始,長度爲2的32位浮點數x(也就是說x佔了前8個字節),再申明一個從第4個字節開始,長度爲1的32位浮點數y,那麼這裏的yx實際上就是重疊的,x已經佔了8個字節,而y是從第4個字節開始的。既然是重疊的,那麼改變x勢必會影響到y,這裏x類型化數組的第一個元素賦值爲7,那麼在ArrayBuffer中便是00000000 00000000 00000000 00000111y是從第四個字節開始,也就是從00000111開始, 因此y也是00000111也就是7了。

類型化數組與常規數組的區別

類型化數組實質上是二進制數據,而ArrayBuffer這段區域又是指定長度的,基於這些即可推出其與常規數組的區別:

  • 類型化數組元素都是數字,它不像JS常規數組那樣能夠參雜不一樣類型,好比下面例子?中的賦值就是無效的

  • 類型化數組長度固定

  • 全部元素初始化爲0

var  a = new Int8Array(3)
a[0] = 'hello'
a[0] // =>0 顯示a[0]依然未定義
a[0] = '8'
a[0]  // = > 8 可是注意類型的自動轉換,當可被轉換成數字時,JS會自動將其轉成數值

DataView

既然本質是在操做二進制數據,那麼就涉及到「高位優先(big-endian)」仍是「低位優先(little-endian)」的數據傳輸問題,DataView的一整套API中就涉及到解決該問題,在當前的大部分CPU架構中的字節傳輸順序都是使用低位優先,而在大部分的網絡協議中使用的字節順序倒是高位優先(好比HTTP協議),它的一系列get方法中就能夠設置字節的處理順序。DataView也是一種視圖,它的原理並不難,詳細的dataview的API能夠看前面提到的博客中的DataView章節。mark?ArrayBuffer:類型化數組

類型化數組的應用

二進制數據的接口主要應用於文件,在JS中涉及文件處理的API幾乎均可以應用ArrayBuffer,主要是Ajax,File,Canvas。這幾個例子等下再碼,爭取寫出跟前面博客不同的東西,先搬磚……

相關文章
相關標籤/搜索