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言語相当 | 主な用途 |
|---|---|---|---|
Int8Array | 1バイト | int8_t | 符号付きバイトデータ |
Uint8Array | 1バイト | uint8_t | 生バイトストリーム |
Uint8ClampedArray | 1バイト | uint8_t | Canvasピクセルデータ |
Int16Array | 2バイト | int16_t | 音声サンプル |
Uint16Array | 2バイト | uint16_t | Unicodeコードユニット |
Int32Array | 4バイト | int32_t | ビットマップデータ |
Uint32Array | 4バイト | uint32_t | ネットワークパケット |
Float32Array | 4バイト | float | 3Dグラフィックス(WebGL) |
Float64Array | 8バイト | double | 科学技術計算 |
BigInt64Array | 8バイト | int64_t | 大きな整数ID |
BigUint64Array | 8バイト | 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ピクセル操作
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; // グレースケール化
}
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を選択しましょう。
