如果要儲存一組二進位資料,可以使用 ArrayBuffer
,它從 ES6 之後成為標準之一,建構 ArrayBuffer
實例時,必須指定位元組長度,例如:
let buf = new ArrayBuffer(32); // 32 個位元組
console.log(buf.byteLength); // 顯示 32
你沒辦法直接改變 ArrayBuffer
實例的內容,只能透過 byteLength
特性取得長度,slice
方法切割 ArrayBuffer
。
若要改變或取得 ArrayBuffer
內容,方式之一是透過 TypedArray
,有以下幾個子類型:
Int8Array
:8 位有號整數,長度一位元組Uint8Array
:8 位無號整數,長度一位元組Uint8ClampedArray
:8 位無號整數,長度一位元組,超出 [0, 255] 的值,會設定為 0 或 255。Int16Array
:16 位有號整數,長度二位元組。Uint16Array
:16 位無號整數,長度二位元組。Int32Array
:32 位有號整數,長度四位元組。Uint32Array
:32 位無號整數,長度四位元組。Float32Array
:32 位浮點數,長度四位元組。Float64Array
:64 位浮點數,長度八位元組。
不同的 TypedArray
子類型,檢視、操作 ArrayBuffer
的觀點(View)不同,例如同一個 ArrayBuffer
實例,在不同的 TypedArray
觀點下,每個元素的位元長度不同,因而透過 length
取得元素個數也就不同:
let buf = new ArrayBuffer(32);
let i8arr = new Int8Array(buf);
let i16arr = new Int16Array(buf);
let i32arr = new Int32Array(buf);
console.log(i8arr.length); // 顯示 32
console.log(i16arr.length); // 顯示 16
console.log(i32arr.length); // 顯示 8
buf
有 32 個位元組,也就是 256 個位元,就 Int8Array
來說,8 個位元為一個元素,因此會有 32 個元素,就 Int16Array
來說,16 位元為一個元素,因而會有 16 個元素,同樣地,對 Int32Array
來說,會有 8 個元素。
在設定元素時,對每個元素的觀點,也視不同的 TypedArray
子類型而不同,例如,透過 Uint8Array
來寫入與讀出:
let buf = new ArrayBuffer(5);
let ui8arr = new Uint8Array(buf);
ui8arr[0] = 72; // H
ui8arr[1] = 101; // e
ui8arr[2] = 108; // l
ui8arr[3] = 108; // l
ui8arr[4] = 111; // 0
// 顯示 Hello
console.log(String.fromCharCode.apply(null, ui8arr));
在建構 TypedArray
子類型時,也可以使用類陣列物件,例如:
let ui8arr = new Uint8Array([72, 101, 108, 108, 111]);
// 顯示 Hello
console.log(String.fromCharCode.apply(null, ui8arr));
在建構 TypedArray
之後,操作方法和特性,與 Array
幾乎是完全相同的,可參考 TypedArray API 文件。
TypedArray
的子類型,對待每個元素的觀點是一致的,如果資料中包含了不同類型的元素,例如,同時包含了 8 位整數與 16 位整數,可以使用 DataView
來處理:
let buf = new ArrayBuffer(3);
let dataView = new DataView(buf);
dataView.setInt16(0, 72);
dataView.setInt8(2, 105);
console.log(dataView.getInt16(0));
console.log(dataView.getInt8(2));
由於資料長度不固定,在呼叫 setXXX
、getXXX
時,必須指定位元組偏移量。