Featured image of post JavaScript 類型數組:瀏覽器中的二進位資料處理Featured image of post JavaScript 類型數組:瀏覽器中的二進位資料處理

JavaScript 類型數組:瀏覽器中的二進位資料處理

掌握用於二進位資料處理的 JavaScript 類型陣列:ArrayBuffer、TypedArray 視圖、DataView、字節序、WebAssembly 整合和 Canvas 像素操作。

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 等效常見用例
佔位符_01 位元組佔位符_1有符號位元組資料
佔位符_01 位元組佔位符_1原始位元組流
佔位符_01 位元組佔位符_1畫布像素資料
佔位符_02 個位元組佔位符_1音訊樣本
佔位符_02 個位元組佔位符_1Unicode 代碼單元
佔位符_04 位元組佔位符_1點陣圖資料
佔位符_04 位元組佔位符_1網路封包
佔位符_04 位元組佔位符_13D 圖形 (WebGL)
佔位符_08 位元組佔位符_1科學計算
佔位符_08 位元組佔位符_1大整數 ID
佔位符_08 位元組佔位符_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 的顯式位元組序參數消除了所有猜測。


畫布像素操作

ImageDataUint8ClampedArray 支持,支援直接像素存取:

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.MemoryArrayBuffer 支持,允許直接記憶體共享:

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