型付き配列(TypedArray)

目次

型付き配列(TypedArray)とは

下記の型付き配列の総称です。プログラムでは TypedArray を使用するのではなく、下記のいずれかを使用します。

値の範囲サイズ (バイト数)Web IDL 型
Int8Array-128 から 1271byte
Uint8Array0 から 2551octet
Uint8ClampedArray0 から 2551octet
Int16Array-32768 から 327672short
Uint16Array0 から 655352unsigned short
Int32Array-2147483648 から 21474836474long
Uint32Array0 から 42949672954unsigned long
Float16Array-65504 から 655042なし
Float32Array-3.4E38 から 3.4E38 および 1.2E-38 (最小の正の数)4unrestricted float
Float64Array-1.8E308 から 1.8E308 および 5E-324 (最小の正の数)8unrestricted double
BigInt64Array-263 to 263 - 18bigint
BigUint64Array0 to 264 - 18bigint

Uint8ClampedArray は固定されたという意味を持つ配列です。0~255 以外の値を格納する場合、Uint8Array は下位8バイトの値が格納されますが、Uint8ClampedArray は 0 以下であれば 0、255 以上であれば 255 が格納されます。

型付き配列の作成

new TypedArray()

引数を省略すると要素数0個の型付き配列を作成します。

const arr = new Int16Array();

new TypedArray(length)

数値を指定すると指定した個数の要素を持つ型付き配列を作成します。

const arr = new Int16Array(3);
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;

new TypedArray(iterableObject)

配列を指定すると配列の各要素を要素とする型付き配列を作成します。

const arr = new Int16Array([1, 2, 3]);

Set など、反復可能オブジェクトを指定しても各要素を要素とする型付き配列を作成します。

const set = new Set([1, 2, 3]);
const arr = new Int16Array(set);

他の型付き配列を引数にすることもできます。要素のビット数が小さくなる場合、あふれたビットは捨てられます。

const arr1 = new Int16Array([1, 2, 3]);
const arr2 = new Int16Array(arr1);

new TypedArray(buffer, offset, length)

上記までの例では、型付き配列が使用する実メモリとして ArrayBuffer を内部で自動生成します。buffer を指定することで、別に作成した ArrayBufferSharedArrayBuffer を使用した型付き配列を作成することもできます。下記の例ではまず 6 バイトの ArrayBuffer を確保し、これを2バイト×3要素からなる Int16Array 型付き配列にマッピングしています。

const buffer = new ArrayBuffer(6);
const arr = new Int16Array(buffer);

offset (バイト数)と length (要素数)を指定することもできます。下記の例では 12 バイトの ArrayBuffer を確保し、前半の 6 バイトを arr1 に、後半の 6 バイトを arr2 にマッピングしています。length を省略した場合の残りのバイト数がすべて割り当てられます。

const buffer = new ArrayBuffer(12);
const arr1 = new Int16Array(buffer, 0, 3);   // オフセット0バイト目から3要素
const arr2 = new Int16Array(buffer, 6);      // オフセット6バイト目から残り個数分

バッファーがリサイズ可能な場合、length を指定していると型付き配列の要素数は変動しませんが、length を指定していない場合、バッファーサイズの変更により要素数も変動します。

const buffer = new ArrayBuffer(6, { maxByteLength: 12 });
const arr = new Int16Array(buffer);    // 6バイト分3要素マッピングされる
console.log(arr.length);               // => 要素数は3
buffer.resize(12);                     // バッファサイズを6バイトから12バイトにリサイズ
console.log(arr.length);               // => 要素数が3から6に変わる

TypeArray.from(arrayLike, mapFn, thisArg)

配列、型付き配列、Set、文字列などの反復可能オブジェクト arrayLike から型付き配列を作成します。

arr = Int16Array.from([1, 2, 3]);                  // 配列
arr = Int16Array.from(new Int16Array([1, 2, 3]));  // 型付き配列
arr = Int16Array.from(new Set([1, 2, 3]));         // Set
arr = Int16Array.from("123");                      // 文字列

mapFn は省略可能で、指定する場合は初期化時に各要素に対して実行する関数を指定します。下記の例では 1, 2, 3 の 2倍にインデックス値 i を加えた 2, 5, 8 の要素を持つ型付き配列が作成されます。

const arr = Int16Array.from([1, 2, 3], (v, i) => v * 2 + i);

thisArg も省略可能で、指定する場合は mapFn の中で this として参照されるオブジェクトを指定します。下記の例では thisArg として文字から数値への変換マッピング map を渡しています。アロー関数を用いると this の対象が変わるのでうまく動きません。

const map = { "A": 1, "B": 2, "C": 3 }
const arr = Uint8Array.from(["A", "B", "C"], function (v) { return this[v]; }, map);

TypedArray.of(e1, e2, ...)

引数配列を要素とする型付き配列を作成します。

const arr = Uint8Array.of(1, 2, 3);

配列の長さ

typedArray.length

型付き配列要素の個数を返します。代入はできません。

const arr = new Int16Array([1, 2, 3]);
console.log(arr.length);                    // => 3

TypedArray.BYTES_PER_ELEMENT

ひとつの要素が使用するバイト数を返します。

console.log(Int16Array.BYTES_PER_ELEMENT);  // => 3

ArrayBuffer の情報

typedArray.buffer

型付き配列要素に割り当てられた ArrayBuffer を返します。

const buffer = new ArrayBuffer(6);
const arr = new Int16Array(buffer);
console.log(arr.buffer);                    // => ArrayBuffer(6)

typedArray.byteLength

型付き配列要素に割り当てられた ArrayBuffer のバイト数を返します。

const buffer = new ArrayBuffer(6);
const arr = new Int16Array(buffer);
console.log(arr.byteLength);                // => 6

typedArray.byteOffset

型付き配列要素に割り当てられた ArrayBuffer のオフセット(バイト数)を返します。

const buffer = new ArrayBuffer(12);
const arr = new Int16Array(buffer, 4, 3);
console.log(arr.byteOffset);                // => 4

型付き配列のループ

for (...)

型付き配列は for 文で回すことができます。

const arr = new Int16Array([1, 2, 3]);
for (var i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}
const arr = new Int16Array([1, 2, 3]);
for (var i in arr) {
  console.log(arr[i]);
}
const arr = new Int16Array([1, 2, 3]);
for (var n of arr) {
  console.log(n);
}

typedArray.forEach(fn, thisArg)

各要素に対して関数 fn を実行します。v は要素の値、i はインデックスを示します。

const arr = new Int16Array([1, 2, 3]);
arr.forEach((v, i) => {
  console.log(`index: ${i}, value: ${v}`);
});

thisArg は省略可能で、関数の中で this として参照されるオブジェクトを指定します。アロー関数では this は関数外スコープの this となるので function を使用してください。

const map = new Map([[1, "A"], [2, "B"], [3, "C"]]);
const arr = new Int16Array([1, 2, 3]);
arr.forEach(function(v, i) {
  console.log(`index: ${i}, value: ${v}, map: ${this.get(v)}`);
}, map);

typedArray.entries()

keyvalue からなる反復可能オブジェクトを返します。

const arr = new Int16Array([100, 200, 300]);
for (var e of arr.entries()) {
  console.log(`key:${e[0]} value:${e[1]}`);
}

typedArray.keys()

key の反復可能オブジェクトを返します。

const arr = new Int16Array([100, 200, 300]);
for (var key of arr.keys()) {
  console.log(`key:${key} value:${arr[key]}`);
}

typedArray.values()

value の反復可能オブジェクトを返します。

const arr = new Int16Array([100, 200, 300]);
for (var value of arr.values()) {
  console.log(`value:${value}`);
}

typedArray.map(func, thisArg)

型付き配列の各要素に対して関数 func を実行し、その戻り値を要素とする配列を返します。thisArg は省略可能で、関数内で this として参照される値です。関数の引数には、要素値(value)、要素のインデックス(index)、型付き配列自体(array)が渡されます。下記の例は、配列の各要素を2倍にした型付き配列を返します。

const arr1 = new Int16Array([1, 2, 3]);
const arr2 = arr1.map((value, index, array) => value * 2);
console.log(arr2);                  // => Int16Array(3) [2, 4, 6]

typedArray.reduce(func, initial)

配列の各要素に対して関数 func を実行します。関数の引数には、アキュムレータ(acc)、要素値(value)、要素のインデックス(index)、配列自体(array) が渡されます。initial を指定した場合、1回目の関数呼び出し時の acc の値は initial となります。initial を省略した場合、最初の要素に対する関数は呼ばれず、最初の要素の値を acc として 2個目の要素に対する関数が呼ばれます。次回以降は関数の戻り値を acc として次の要素に対する関数が呼ばれ、最後の要素に対する関数の戻り値が reduce() の戻り値となります。下記の例では各要素を2倍した合計を求めています。

const arr = new Int16Array([100, 200, 300]);
const n = arr.reduce((acc, value, index, array) => {
  console.log(`acc:${acc} value:${value} index:${index} array:${array}`);
  return acc + value * 2;
}, 0);
console.log(n);
// => acc: 0 value:100 index:0 array:100,200,300
// => acc: 200 value:200 index:1 array:100,200,300
// => acc: 600 value:300 index:2 array:100,200,300
// => 1200

initial の 0 を指定しない場合は、100 + 200*2 + 300*2 = 1100 となり、1200 とはならない点に注意してください。

const arr = new Int16Array([100, 200, 300]);
const n = arr.reduce((acc, value, index, array) => {
  console.log(`acc:${acc} value:${value} index:${index} array:${array}`);
  return acc + value * 2;
});
console.log(n);
// => acc: 100 value:200 index:1 array:100,200,300
// => acc: 500 value:300 index:2 array:100,200,300
// => 1100

typedArray.reduceRight(func, initial)

要素を右から順に処理していく以外は reduce() と同様です。

const arr = new Int16Array([100, 200, 300]);
const n = arr.reduceRight((acc, value, index, array) => {
  console.log(`acc:${acc} value:${value} index:${index} array:${array}`);
  return acc + value * 2;
}, 0);
console.log(n);
// => acc:0 value:300 index:2 array:100,200,300
// => acc:600 value:200 index:1 array:100,200,300
// => acc:1000 value:100 index:0 array:100,200,300
// => 1200

配列の検査

typedArray.indexOf(elm)

配列の中に elm とマッチする要素が最初に出現するインデックスを返します。見つからない場合は -1 を返します。

const arr = new Int16Array([100, 200, 300]);
console.log(arr.indexOf(300));       // => 2

typedArray.lastIndexOf(elm)

配列の中に elm とマッチする要素が最後に出現するインデックスを返します。見つからない場合は -1 を返します。

const arr = new Int16Array([3, 5, 8, 5, 1]);
console.log(arr.lastIndexOf(5));       // => 3

typedArray.includes(elm)

elm にマッチする要素の有無を true/false で返却します。

const arr = new Int16Array([100, 200, 300]);
console.log(arr.includes(200));         // => true
console.log(arr.includes(400));         // => false

index in typedArray

該当のインデックスの要素が存在するかどうかを調べるには index in typedArray を用います。

const arr = new Int16Array([100, 200, 300]);
console.log(2 in arr);                  // => true
console.log(3 in arr);                  // => false

typedArray.every(func, thisArg)

配列の各要素に対して関数 func を実行し、func の戻り値がすべて真であれば、true を、さもなくば false を返します。thisArg は省略可能で、関数の中で this として参照される値を指定することができます。関数の引数には、要素値(value)、要素のインデックス(index)、配列自体(array)が渡されます。下記の例は、配列要素がすべて 80以上であるかを確認しています。

const arr = new Int16Array([69, 87, 93, 65, 88]);
const bool = arr.every((value, index, array) => {
  return (value >= 80);
});
console.log(bool);                   // => false

typedArray.some(func[, thisArg])

配列の各要素に対して関数 func を実行し、func の戻り値がひとつでも真であれば、true を、さもなくば false を返します。thisArg は省略可能で、関数の中で this として参照される値を指定することができます。関数の引数には、要素値(value)、要素のインデックス(index)、配列自体(array)が渡されます。下記の例は、配列要素がひとつでも 80以上であるかを確認しています。

const arr = new Int16Array([69, 87, 93, 65, 88]);
const bool = arr.some((value, index, array) => {
  return (value >= 80);
});
console.log(bool);                   // => true

typedArray.find(func, thisArg)

配列の各要素に対して関数 func を実行し、func の戻り値がはじめて真となる要素の値を返します。見つからない場合は undefined を返します。thisArg は省略可能で、関数の中で this として参照される値を指定することができます。関数の引数には、要素値(value)、要素のインデックス(index)、配列自体(array)が渡されます。下記の例は、配列要素のうち 80 以上である要素の値を返します。

const arr = new Int16Array([69, 87, 93, 65, 88]);
const n = arr.find((value, index, array) => value >= 80);
console.log(n);                      // => 87

typedArray.findLast(func, thisArg)

find() とほぼ同様ですが、配列の最後から前方に向かって検索する点が異なります。

const arr = new Int16Array([69, 87, 93, 65, 88]);
const n = arr.findLast((value, index, array) => value >= 80);
console.log(n);                      // => 88

typedArray.findIndex(func, thisArg)

find() とほぼ同様ですが、値ではなくインデックスを返すことと、見つからなかった場合に -1 を返す点が異なります。

const arr = new Int16Array([69, 87, 93, 65, 88]);
const index = arr.findIndex((value, index, array) => value >= 80);
console.log(index);                  // => 1

typedArray.findLastIndex(func, thisArg)

findLast() とほぼ同様ですが、値ではなくインデックスを返すことと、見つからなかった場合に -1 を返す点が異なります。

const arr = new Int16Array([69, 87, 93, 65, 88]);
const index = arr.findLastIndex((value, index, array) => value >= 80);
console.log(index);                  // => 4

配列要素の取り出しと追加

typedArray.at(n)

配列の n 番目(0~)の要素を取り出します。負数を指定すると最後から数えて n番目(1~)の要素を取り出します。

const arr = new Int16Array([100, 200, 300]);
consolg.log(arr.at(0));          // => 100
console.log(arr.at(1));          // => 200
console.log(arr.at(-1));         // => 300

typedArray.slice(start, end)

0 から数えて start 番目から end - 1 番目までの要素を抜き出した新たな型付き配列を返します。end を省略した場合は最後までの要素を返します。typedArray は変化しません。元の typedArray と新たな型付き配列で ArrayBuffer の共有も行いません。

const arr = new Int16Array([100, 200, 300, 400, 500, 600]);
console.log(arr.slice(2, 5));    // => Int16Array(3) [300, 400, 500]
console.log(arr);

typedArray.subarray(start, end)

0 から数えて start 番目から end - 1 番目までの要素を抜き出した新たな型付き配列を返します。end を省略した場合は最後までの要素を返します。元の typedArray と新たな型付き配列で ArrayBuffer を共有します。片方を変更すると他方の値も変更されます。

const arr1 = new Int16Array([100, 200, 300, 400, 500, 600]);
arr2 = arr1.subarray(2, 5);
console.log(arr1);      // => Int16Array(6) [100, 200, 300, 400, 500, 600]
console.log(arr2);      // => Int16Array(3) [300, 400, 500]

typedArray.filter(func, thisArg)

配列の各要素に対して関数 func を実行し、func の戻り値が真となる要素からなる新たな型付き配列を返します。見つからない場合は空配列を返します。thisArg は省略可能で、関数の中で this として参照される値を指定することができます。関数の引数には、要素値(value)、要素のインデックス(index)、配列自体(array)が渡されます。下記の例は、配列要素のうち 80 以上である要素からなる型付き配列を返します。

const arr1 = new Int16Array([69, 87, 93, 65, 88]);
const arr2 = arr1.filter((value, index, array) => value >= 80);
console.log(arr2);                 // => Int16Array(3) [87, 93, 88]

配列の並べ替え

typedArray.sort(func)

typedArray をソートしてその結果の配列を返します。typedArray 自身もソートされます。

const arr = new Int16Array([3, 7, 8, 1]);
console.log(arr.sort());           // => Int16Array(4) [1, 3, 7, 8]
console.log(arr);                  // => Int16Array(4) [1, 3, 7, 8]

ソート関数 func を指定することもできます。ソート関数では等しければ 0 を、小さければ負の値を、大きければ正の値を返します。下記の例では大きな値順にソートしています。

const arr = new Int16Array([3, 7, 8, 1]);
arr.sort((a, b) => (a == b) ? 0 : (a < b) ? 1 : -1);
console.log(arr);                  // => Int16Array(4) [8, 7, 3, 1]

typedArray.toSorted(func)

typedArray をソートしてその結果の配列を返します。typedArray 自身はソートされません。他の機能は sort() と同様です。

const arr = new Int16Array([3, 7, 8, 1]);
console.log(arr.toSorted());       // => Int16Array(4) [1, 3, 7, 8]
console.log(arr);                  // => Int16Array(4) [3, 7, 8, 1]

typedArray.reverse()

typedArray を逆順に並べ替えてその結果の配列を返します。typedArray 自身も並べ替えられます。

const arr = new Int16Array([1, 2, 3]);
console.log(arr.reverse());           // => Int16Array(3) [3, 2, 1]
console.log(arr);                     // => Int16Array(3) [3, 2, 1]

typedArray.toReversed()

typedArray を逆順に並べ替えてその結果の配列を返します。typedArray 自身は並べ替えられません。

const arr = new Int16Array([1, 2, 3]);
console.log(arr.toReversed())         // => Int16Array(3) [3, 2, 1]
console.log(arr);                     // => Int16Array(3) [1, 2, 3]

配列から文字列への変換

typedArray.toString()

配列を文字列に変換します。

const arr = new Int16Array([1, 2, 3]);
console.log(arr.toString());        // => "1,2,3,A,B,C"

typedArray.toLocaleString(locale, option)

配列要素をロケールに従った文字列に変換します。ロケールを locale で指定することもできます。option には単位や貨幣記号などの情報を渡すこともできます。

const arr = new Int16Array([9800, 16500]);
console.log(arr.toLocaleString());                // => "9,800,16,500"
console.log(arr.toLocaleString("ja"));            // => "9,800,16,500"
console.log(arr.toLocaleString("ja", { style: "currency", currency: "JPY"}));  // => "¥9,800,¥16,500"

typedArray.join(separator)

typedArray の各要素の値を separator で連結した文字列を返します。separator を省略した場合はカンマ(,)で連結します。

const arr = new Int16Array(["23", "86", "62"]);
console.log(arr.join());           // => 23,86,62
console.log(arr.join(" "));        // => 23 86 62
console.log(arr.join("-"));        // => 23-86-62

配列要素の変更

typedArray.set(array, offset)

0 から数えて offset 番目の要素以降を配列または型付き配列 array の要素で上書きします。typedArray 自身が変更されます。offset を省略した場合は 0 番目から上書きされます。

const arr = new Int16Array([0, 1, 2, 3, 4, 5, 6]);
arr.set([333, 444, 555], 3);
console.log(arr);                      // => Int16Array(7) [0, 1, 2, 333, 444, 555, 6]

0 から数えて start 番目から end - 1 番目の要素の値を value に置換します。typedArray 自身を書き換えます。start が省略された場合は 0番目から、end が省略された場合は最後までを置換します。

const arr = new Int16Array([0, 1, 2, 3, 4, 5]);
arr.fill(999, 2, 4);
console.log(arr);           // => Int16Array(6) [0, 1, 999, 999, 4, 5]

typedArray.fill(value, start, end)

0 から数えて start 番目から end - 1 番目の要素の値を value に置換します。typedArray 自身を書き換えます。start が省略された場合は 0番目から、end が省略された場合は最後までを置換します。

const arr = new Int16Array([0, 1, 2, 3, 4, 5]);
arr.fill(999, 2, 4);
console.log(arr);           // => Int16Array(6) [0, 1, 999, 999, 4, 5]

typedArray.with(index, value)

0 から数えて index 番目の要素を value に置換したものを返します。typedArray は変更されません。

const arr = new Int16Array([0, 1, 2, 3, 4, 5]);
console.log(arr.with(3, 999));    // => Int16Array(6) [0, 1, 2, 999, 4, 5]
console.log(arr);                 // => Int16Array(6) [0, 1, 2, 3, 4, 5]

typedArray.copyWithin(target, start, end)

start 番目から end - 1 番目の要素を、target 番目からの要素と置き換えます。typedArray 自体を書き換えます。start が省略された場合は 0番目から、end が省略された場合は最後までをコピーします。下記の例では 0 から数えて 8番目から 10 - 1 = 9番目の要素を、2番目からの要素にコピーしています。

const arr = new Int16Array([0, 1, 2, 3, 4, 5, 6, 7, 888, 999]);
arr.copyWithin(2, 8, 10);
console.log(arr);                 // => [0, 1, 888, 999, 4, 5, 6, 7, 888, 999]

分割代入

型付き配列でも下記のような分割代入が可能です。

const arr = new Int16Array([1, 2, 3, 4, 5, 6]);
[a, b] = arr;
console.log(a);              // => 1
console.log(b);              // => 2

途中をスキップすることもできます。

[a, b, , c] = arr;
console.log(a);              // => 1
console.log(b);              // => 2
console.log(c);              // => 4

... を用いて残りの要素を配列として受け取ることもできます。

[a, b, ...c] = arr;
console.log(a);              // => 1
console.log(b);              // => 2
console.log(c);              // => [3, 4, 5, 6]