カタバミさんのプログラミングノート

日曜プログラマーがプログラミング関係のメモを記録するブログです。

Uint8Arrayのmap関数の注意あるいはTextEncoder.encodeの戻り値の注意

Uint8Array.of(0, 1, 2).map(x => x) // Uint8Array(3) [0, 1, 2]
Uint8Array.of(0, 1, 2).map(x => 0.1) // Uint8Array(3) [0, 0, 0] !?
Uint8Array.of(0, 1, 2).map(x => "a") // Uint8Array(3) [0, 0, 0] !?

現在の仕様ではUint8Array.map関数はUint8Array型を返します。Uint8Array.mapの結果は強制的にUint8Arrayの要素に変換されるため、Array.map関数と同じ感覚で使用すると想定外の挙動が起きます。この挙動はArray.from関数でArray型にしてしまうことで回避できます。TextEncoder.encode関数の戻り値(Uint8Array型)に対してmap関数を適用したらハマったので共有します。

Array.from関数による対処例

Array.from(Uint8Array.of(0, 1, 2)).map(x => 0.1) // [0.1, 0.1, 0.1]
Array.from(Uint8Array.of(0, 1, 2)).map(x => "a") // ["a", "a", "a"]

TextEncoder.encodeにおける再現と対処

(new TextEncoder('utf-8')).encode("abc").map(ch => ch.toString(16))
// Uint8Array(3) [61, 62, 63] ※整数に変換されている。

Array.from((new TextEncoder('utf-8')).encode("abc")).map(ch => ch.toString(16))
// ["61", "62", "63"] ※文字列のまま

TextEncoder.encodeにおける再現と対処(padStart関数が無意味になる)

(new TextEncoder('utf-8')).encode("abc").map(ch => ch.toString(16).padStart(3, "0"))
// Uint8Array(3) [ 61, 62, 63 ]
Array.from((new TextEncoder('utf-8')).encode("abc")).map(ch => ch.toString(16).padStart(3, "0"))
// Array(3) [ "061", "062", "063" ]

参考