potisanのプログラミングメモ

プログラミング素人です。昔の自分を育ててくれたネット情報に少しでも貢献できるよう、情報を貯めていこうと思っています。Windows環境のC++やC#がメインです。

JavaScript TypedArrayのmapメソッドの注意(強制的な型変換)

  • TypedArray.prototype.map(...)
    • 変換結果がUint8→予想通りの結果
    • 変換結果が文字列等→予想外の結果(e.g. [0, 0, 0, ...]

TypedArray.prototype.mapの戻り値はTypedArrayであり、各要素はTypedArrayの要素型に変換されます。例えばUint8Array.prototype.mapメソッドの戻り値はUint8Arrayであり、各要素はUint8へ変換されます。Arraymapメソッドと同じ感覚で文字列へ変換した場合、戻り値はすべて0のTypedArrayになります。

上記は[...Array]Array.from関数、Array関数でArray型へ変換することで回避できます。ただし、変換のコストはかかります。

const uint8Array1 = Uint8Array.from([0, 1, 2, 3, 4]);
console.log(uint8Array1);
// Uint8Array(5) [ 0, 1, 2, 3, 4 ]

// 次のコードは一見成功してしまう。
// 実際にはtoStringで作成された文字列"X"がUint8へキャストされている。
console.log(uint8Array1.map(x => x.toString()));
// Uint8Array(5) [ 0, 1, 2, 3, 4 ]

// 次のコードは失敗する。
// toStringで作成された文字列"0xXX"がUint8へキャストされてすべて0になる。
console.log(uint8Array1.map(x => "0x"+x.toString(16).padStart(2, '0')));
// Uint8Array(5) [ 0, 0, 0, 0, 0 ]

// 一度Arrayへ変換すれば成功する。ただし変換コストはかかる。
console.log([...uint8Array1].map(x => "0x"+x.toString(16).padStart(2, '0')));
console.log(Array.from(uint8Array1).map(x => "0x"+x.toString(16).padStart(2, '0')));
// Array(5) [ "0x00", "0x01", "0x02", "0x03", "0x04" ]
// Array(5) [ "0x00", "0x01", "0x02", "0x03", "0x04" ]

参考