mozilla

JavaScript 型別陣列

編撰中
本頁仍未完成

當 Webapp 有了視頻、音頻操作及用 WebSockets 存取原始資料等等的功能而變得越來越強大,讓 JavaScript 代碼可以快速、簡單地操作原始二進制資料的好處就越來越明顯。以前唯一的解法是視原始資料為字串並用 charCodeAt() 方法讀取資料緩衝的位元組。

然而,由於需要多次型別轉換(特別是二進制資料並非以位元組計算,如32位元整數或浮點數),這個解法既慢又容易發生錯誤。

JavaScript 型別陣列提供了存取二進制資料更有效率的機制。

緩衝與視圖:型別陣列的架構

為了追求最大的可朔性與效率,JavaScript 型別陣列的實作分為緩衝視圖。一個緩衝(以類別 ArrayBuffer 實作)為代表一塊資料資料的物件,它沒有任何格式,也沒有任何存取其內容的機制。想存取一個緩衝所佔的記憶體必須用一個視圖。一個視圖提供了一種前後關係 — 資料型別、起始偏移與元素的數目 — 使得資料變成真實的型別陣列。視圖以類別 ArrayBufferView 與其子類別實作。

使用視圖與緩衝

先來建立一個16位元組的緩衝:

var buffer = new ArrayBuffer(16);

在這個時候,我們有位元組全部初始為0的一塊記憶體,但是用它做不了什麼事。我們只能確認它的確是16的位元組的長度:

if (buffer.byteLength == 16) {
  alert("沒錯,是16個位元組。");
} else {
  alert("糟糕,長度不對!");
} 

要用這個緩衝搞點花樣之前,建立一個視圖是必需的。來建立一個視圖把這個緩衝當作32位元的有符號整數:

var int32View = new Int32Array(buffer);

這樣就可以把它當作一般的陣列以存取欄位:

for (var i=0; i<int32View.length; i++) {
  int32View[i] = i*2;
}

這會把此陣列的4個欄位以 0, 2, 4, 6 填滿(4個4位元組,總共16位元組)。

同一份資料的多個視圖

考慮在同一份資料上建立多個視圖的有趣情形。舉例來說,繼續使用上面的代碼:

var int16View = new Int16Array(buffer);

for (var i=0; i<int16View.length; i++) {
  console.log("Entry " + i + ": " + int16View[i]);
}

雖然該緩衝上已有一個32位元的視圖,這裡建立了同一個緩衝上的16位元整數視圖,這裡的輸出為 0, 0, 2, 0, 4, 0, 6, 0。

繼續考慮這種情況:

int16View[0] = 32;
console.log("現在32位元陣列的欄位0是" + int32View[0]);

輸出為"現在32位元陣列的欄位0是32"。也就是,這兩個陣列真的是同一個資料緩衝的在不同格式下的看法。其他 view types 也是同樣的情形。

處理複雜的資料結構

在單一個緩衝使用不同型別、不同起始偏移的多個視圖以操作資料物件含有的多個資料型別。這個方法可以用在使用 WebGL 、資料檔案、js-ctypes 時遇到的複雜的資料結構。

考慮這個 C 結構:

struct someStruct {
  unsigned long id;
  char username[16];
  float amountDue;
}; 

可以用以下方法存取含有這種資料格式的緩衝:

var buffer = new ArrayBuffer(24);

// ... 將資料讀入緩衝 ...

var idView = new Uint32Array(buffer, 0, 1);
var usernameView = new Uint8Array(buffer, 4, 16);
var amountDueView = new Float32Array(buffer, 20, 1);

舉例來說,可以用 amountDueView[0] 存取 amountDue。

注:C 結構的 data structure alignment 是與使用平台有關,須小心這些填充上的差異。

兼容

WebKit 上也有型別陣列。Chrome 7 有支援 ArrayBufferFloat32ArrayInt16ArrayUint8Array。Chrome 9 加上了DataView 物件的支援。

規範

Document Tags and Contributors

標籤: 
Contributors to this page: Kennyluck, teoli
最近更新: teoli,