JavaScript 的原生 Number 類型(IEEE 754 雙精度浮點數)對於二進位資料來說效率低。早期的解決方案涉及在普通數組中手動打包字節,這種方法速度慢且容易出錯。 ECMAScript 2015 正式化了型別數組,為 JavaScript 帶來了類似 C 的記憶體管理。這種三層架構 — ArrayBuffer、TypedArray 視圖和 DataView — 支援在瀏覽器和 Node.js 中進行高效能二進位資料處理。
ArrayBuffer基金會
ArrayBuffer 表示固定長度的原始二進位緩衝區。它不能直接讀取或寫入 - 您必須使用視圖:
const buffer = new ArrayBuffer(16); // 16 bytes
console.log(buffer.byteLength); // 16
緩衝區可以使用 structuredClone 在 Web Worker 之間傳輸,或使用 resizable 標誌調整大小。 slice() 方法建立部分副本。重要的是,緩衝區本身沒有類型資訊——它只是一個連續的記憶體區塊。
類型化數組視圖
類型化數組視圖為 ArrayBuffer 提供了一個類型化視窗。每個視圖將緩衝區的位元組解釋為特定數字類型的元素:
const buffer = new ArrayBuffer(8);
const int32 = new Int32Array(buffer); // 2 × 32-bit integers
const float64 = new Float64Array(buffer); // 1 × 64-bit float
以下是類型化數組類型及其特徵的完整參考:
| 構造函數 | 元素尺寸 | C 等效 | 常見用例 |
|---|---|---|---|
| 佔位符_0 | 1 位元組 | 佔位符_1 | 有符號位元組資料 |
| 佔位符_0 | 1 位元組 | 佔位符_1 | 原始位元組流 |
| 佔位符_0 | 1 位元組 | 佔位符_1 | 畫布像素資料 |
| 佔位符_0 | 2 個位元組 | 佔位符_1 | 音訊樣本 |
| 佔位符_0 | 2 個位元組 | 佔位符_1 | Unicode 代碼單元 |
| 佔位符_0 | 4 位元組 | 佔位符_1 | 點陣圖資料 |
| 佔位符_0 | 4 位元組 | 佔位符_1 | 網路封包 |
| 佔位符_0 | 4 位元組 | 佔位符_1 | 3D 圖形 (WebGL) |
| 佔位符_0 | 8 位元組 | 佔位符_1 | 科學計算 |
| 佔位符_0 | 8 位元組 | 佔位符_1 | 大整數 ID |
| 佔位符_0 | 8 位元組 | 佔位符_1 | 密碼學 |
建立子數組而不進行複製使用 subarray():
const full = new Uint8Array([10, 20, 30, 40]);
const partial = full.subarray(1, 3); // [20, 30] — zero copy
複雜結構的資料視圖
當緩衝區包含混合資料類型時,DataView 提供您所需的靈活性。它允許以顯式類型和位元組順序以任意位元組偏移量進行讀寫:
const buffer = new ArrayBuffer(8);
const dv = new DataView(buffer);
dv.setUint16(0, 0x4D42, true); // little-endian 'BM' signature
dv.setUint32(2, 1024, true); // file size
dv.setUint16(6, 54, true); // pixel offset
littleEndian 參數對於跨平台相容性至關重要。由於其靈活性,DataView 比類型化視圖稍慢,但它是解析 BMP、PNG 或 WAV 標頭等二進位檔案格式的正確工具。
位元組序和跨平台處理
Endianness 指的是位元組順序:big-endian 首先儲存最高有效位元組,little-endian 首先儲存最低有效位元組。您可以在運行時檢測平台位元組順序:
const isLittleEndian = new Uint16Array(
new Uint8Array([0x12, 0x34]).buffer
)[0] === 0x3412;
在使用網路協定(TCP、WebSocket 二進位訊框)、檔案格式(PNG、WAV、MP4)和 WebGPU 緩衝區佈局時,位元組順序很重要。 DataView 的顯式位元組序參數消除了所有猜測。
畫布像素操作
ImageData 由 Uint8ClampedArray 支持,支援直接像素存取:
const ctx = canvas.getContext("2d");
const imageData = ctx.getImageData(0, 0, width, height);
const pixels = imageData.data; // Uint8ClampedArray
for (let i = 0; i < pixels.length; i += 4) {
const gray = 0.299 * pixels[i] + 0.587 * pixels[i+1] + 0.114 * pixels[i+2];
pixels[i] = pixels[i+1] = pixels[i+2] = gray; // grayscale
}
ctx.putImageData(imageData, 0, 0);
這種方法比畫布過濾器方法快得多,並且可以透過 requestAnimationFrame 實現即時視訊處理。
WebAssembly 記憶體集成
類型化陣列是 JavaScript 和 WebAssembly 之間的橋樑。 WebAssembly.Memory 由 ArrayBuffer 支持,允許直接記憶體共享:
const memory = new WebAssembly.Memory({ initial: 1 }); // 1 page = 64KB
const buffer = memory.buffer;
const view = new Uint8Array(buffer);
// Write data, call Wasm function, read results
這種零拷貝模型是高效能 WebAssembly 應用程式的基礎。
效能最佳化
對於數值數據,類型化數組比普通數組具有顯著的效能優勢。使用 new ArrayBuffer(expectedSize) 預先分配緩衝區以避免調整大小。使用 subarray() 而不是 slice() 以避免複製。透過保持類型化陣列存取單態來避免隱藏類別轉換。對於算術密集型代碼,Float64Array 利用 CPU 的本機雙精度管路。
掌握使用類型化陣列進行二進位資料處理可以解鎖應用領域,包括音訊/視訊處理、WebAssembly、遊戲開發和科學計算。對於混合類型解析,請使用 DataView。對於統一數值數組,請使用類型化視圖。對於原始記憶體管理,直接使用 ArrayBuffer 。

