Featured image of post JavaScript Typed Arrays:ブラウザでのバイナリデータ処理 Featured image of post JavaScript Typed Arrays:ブラウザでのバイナリデータ処理

JavaScript Typed Arrays:ブラウザでのバイナリデータ処理

JavaScriptのTyped Arraysを徹底解説。ArrayBuffer、型付き配列ビュー、DataView、エンディアン、WebAssembly連携、Canvasピクセル操作まで網羅。

JavaScriptのネイティブなNumber型(IEEE 754倍精度浮動小数点)はバイナリデータの処理に非効率です。従来は手動でバイトパッキングを行う必要がありましたが、ECMAScript 2015でTyped Arraysが標準化され、C言語に近いメモリ管理がJavaScriptに導入されました。ArrayBuffer、TypedArrayビュー、DataViewの3層アーキテクチャにより、ブラウザ上で高性能なバイナリデータ処理が可能になります。

ArrayBufferの基礎

ArrayBufferは固定長の生バイナリバッファです。直接読み書きはできず、必ずビューを介してアクセスします:

const buffer = new ArrayBuffer(16);      // 16バイト
console.log(buffer.byteLength);          // 16

バッファはstructuredCloneを使ってWeb Worker間で転送できます。slice()メソッドで部分コピーも可能です。ArrayBuffer自体に型情報はなく、単なる連続したメモリ領域です。


型付き配列ビュー

型付き配列ビューは、ArrayBufferに型付きの窓を提供します。各ビューはバッファのバイトを特定の数値型の要素として解釈します:

const buffer = new ArrayBuffer(8);
const int32 = new Int32Array(buffer);    // 32ビット整数×2
const float64 = new Float64Array(buffer); // 64ビット浮動小数点×1

型付き配列の一覧:

コンストラクタ要素サイズC言語相当主な用途
Int8Array1バイトint8_t符号付きバイトデータ
Uint8Array1バイトuint8_t生バイトストリーム
Uint8ClampedArray1バイトuint8_tCanvasピクセルデータ
Int16Array2バイトint16_t音声サンプル
Uint16Array2バイトuint16_tUnicodeコードユニット
Int32Array4バイトint32_tビットマップデータ
Uint32Array4バイトuint32_tネットワークパケット
Float32Array4バイトfloat3Dグラフィックス(WebGL)
Float64Array8バイトdouble科学技術計算
BigInt64Array8バイトint64_t大きな整数ID
BigUint64Array8バイトuint64_t暗号処理

subarray()はコピーなしで部分ビューを作成します:

const full = new Uint8Array([10, 20, 30, 40]);
const partial = full.subarray(1, 3);  // [20, 30] — ゼロコピー

DataViewによる複合構造

バッファに混在するデータ型がある場合、DataViewが適切なツールです。任意のバイトオフセットで、型とエンディアンを明示して読み書きできます:

const buffer = new ArrayBuffer(8);
const dv = new DataView(buffer);
dv.setUint16(0, 0x4D42, true);  // リトルエンディアンで'BM'シグネチャ
dv.setUint32(2, 1024, true);    // ファイルサイズ
dv.setUint16(6, 54, true);      // ピクセルオフセット

littleEndianパラメータはクロスプラットフォーム互換性に不可欠です。DataViewは型付きビューよりやや低速ですが、BMPやPNG、WAVなどのバイナリファイル形式の解析には最適です。


エンディアンとクロスプラットフォーム対応

エンディアンとはバイト順序のことです。ビッグエンディアンは最上位バイトから、リトルエンディアンは最下位バイトから格納します。実行時のプラットフォームエンディアン検出:

const isLittleEndian = new Uint16Array(
  new Uint8Array([0x12, 0x34]).buffer
)[0] === 0x3412;

ネットワークプロトコル、ファイル形式、WebGPUのバッファレイアウトではエンディアンが重要です。DataViewの明示的エンディアンパラメータがあらゆる推測を排除します。


Canvasピクセル操作

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;  // グレースケール化
}
ctx.putImageData(imageData, 0, 0);

CanvasフィルタやWebGLシェーダーと比較しても、Typed Arrayによる直接ピクセル操作は高速で、requestAnimationFrameを用いたリアルタイム映像処理を実現します。


WebAssemblyメモリ統合

Typed ArraysはJavaScriptとWebAssemblyの橋渡し役です。WebAssembly.MemoryはArrayBufferでバックアップされ、直接メモリを共有できます:

const memory = new WebAssembly.Memory({ initial: 1 });
const buffer = memory.buffer;
const view = new Uint8Array(buffer);
// データ書き込み → Wasm関数呼び出し → 結果読み取り

このゼロコピーモデルが、高性能WebAssemblyアプリケーションの基盤です。

Typed Arraysの習得は、音声・動画処理、WebAssembly、ゲーム開発、科学技術計算といった新しいアプリケーション領域への扉を開きます。混在型の解析にはDataView、均一な数値配列には型付きビュー、生メモリ管理にはArrayBufferを選択しましょう。