配列(Array)は我々プログラマにとって馴染み深い要素のひとつです。配列はどんな入門書にも登場し、どんな高度なプログラムにおいても大活躍します。そしてJavaScritpに限らず、他の言語でも配列(あるいはリスト)は登場します。
こんなにも身近な配列ですが、「なんとなく」で使っていて「配列とはなんなのか」「何ができるのか」をあまり把握できていない方も多いと思います(もちろん私もそうです!)。
そこで、配列についてもう一度調べ上げ、情報をまとめてみることにしました。
JavaScriptにおけるArray
一般に配列(Array)とは、複数の値を管理するためのデータ構造です。JavaScriptにおいてもそれは同じで、Arrayは複数の値を持つことができます。
配列の作成
配列の作成には括弧を使ったリテラル記法か、new演算子を使います。
// 配列は複数の値を格納できる
// リテラル
const array = [1, 2, 3, 4];
// newで作成する
const array2 = new Array(1, 2, 3, 4);
newで作成する方法は2通りあります。
const array1 = new Array(5); // サイズが5の配列ができる
const array2 = new Array(1, 2); // [1, 2]ができる
引数が1つのときは配列のサイズを指定したことになり、そのサイズの配列が作成されます。2つ以上の引数を指定したときは配列の要素を指定したことになり、その要素をもつ配列が作成されます。
要素を全く持たない、空の配列を作成することもできます。
// 要素を持たない空の配列
const array1 = [];
const array2 = new Array();
空要素を持つ配列
JavaScriptでは、要素が空である配列を作成することも可能です。
const array = [1,,3]; // [1, empty, 3]
この場合、該当箇所が空となり、アクセスしようとしてもundefinedとなります。
また、newでサイズを指定して配列を作成した場合、全ての要素のデフォルト値は空です。
配列へのアクセス
配列の要素へのアクセスは括弧を使って行います。インデックス(配列の要素番号)を指定することにより、対応した番号の要素にアクセスできます。
インデックスは0から始まります。つまり、一番最初の要素は0番目になります。これは歴史的な理由によります。
// インデックスを使ったアクセス
const array = [1, 2, 3];
console.log(array[0]); // 1
console.log(array[1]); // 2
console.log(array[2]); // 3
存在しないインデックスにアクセスするとundefinedとなります。
const array = [1, 2, 3];
console.log(array[3]); // undefined
また、推奨はしませんが、文字列キーによるアクセスも可能です。
// 文字列キーを使ったアクセス
const array = [1, 2, 3];
console.log(array['0']); // 1
console.log(array['1']); // 2
console.log(array['2']); // 3
配列への値の代入も同様に行えます。
const array = [1, 2, 3];
array[1] = 5; // 2番目に5を代入
console.log(array); // [1, 5, 3]
可変長
JavaScriptの配列は全て可変長です。つまり配列のサイズは固定ではないということです。
配列の長さはlengthプロパティにより調べることができます。
// 配列のサイズを調べる
console.log([1, 2, 3].length); // 3
console.log([1, 2, 3, 4, 5].length); // 5
lengthプロパティに値をセットすることで、配列のサイズを変更できます。
const array = [1];
// 配列を長くする
array.length = 3;
console.log(array); // [1, empty, empty]
// 一度長くした配列を短くする
array.length = 2;
console.log(array); // [1, empty]
配列を伸ばしたとき、新たな領域には何も値が入らず、空になります。また、配列を短くしたとき、はみ出てしまった要素は削除されます。
lengthプロパティの変更だけでなく、一部のメソッドでも長さが変わります。例えば配列の後ろに値を追加するpushメソッドなどがあります。
const array = [1];
array.push(2); // 配列に値「2」を追加する
console.log(array); // [1, 2]
オブジェクト型
JavaScriptの型はプリミティブ型(文字列、数値など)とオブジェクト型(Objectなど)に大別できますが、配列はオブジェクト型になります。
console.log([1, 2] instanceof Object); // true
オブジェクト型なので、配列自体の値は参照値として扱われることに注意が必要です。詳しくは「JavaScriptの変数と配列と参照について」をご覧ください。
また、配列はオブジェクトであるため、常にtruthy(trueとして扱われる)です。空配列もtrue扱いになります。
if([1, 2, 3]) {
console.log('ここは実行される');
}
if([]) {
console.log('ここも実行される');
}
配列に入る値
配列に入る値の型に制限はありません。数値、文字列、オブジェクト、なんでも可能です。
const numArray = [1, 2, 3];
const strArray = ['a', 'b', 'c'];
const objArray = [{x: 1, y: 2}, {x:3, y:4}];
配列の中に配列を含めることも可能です。これは行列などを表現する際に便利です。
const matrix = [
[1, 2],
[3, 4]
];
また、配列の中に複数の型を混在させることも可能です。
const array = [1, '2', {x: 3}];
スプレッド演算子
スプレッド演算子(…)を使用して、配列の値を展開することが可能です。
展開した配列は、他の配列の要素として展開したり、関数呼び出しの引数として扱うことが可能です。
const array1 = [1, 2, 3];
// スプレッド演算子で配列内に配列を展開
const array2 = [4, ...array]; // [4, 1, 2, 3]
// スプレッド演算子で関数呼び出し内に配列を展開
const max = Math.max(...array1); // Math.max(1, 2, 3) と同じ
分割代入
配列のそれぞれの値を別々の変数に代入する、分割代入という機能があります。
// 分割代入でそれぞれの変数に配列の値を代入する
// このコードは以下と同じ:
// const a = 1;
// const b = 2;
const [a, b] = [1, 2];
分割代入には様々なバリエーションがあります。
// a = 1, b= 2, rest = [3, 4, 5]
const [a, b, ...rest] = [1, 2, 3, 4, 5];
// a = 1, b = 3
const [a,,b] = [1, 2, 3];
Iterable
配列は@@iteratorメソッドを実装しており、反復処理が可能なIterableです。@@iteratorシンボルは定数Symbol.iterableで取得できます。
// iteratorを取得する
const iterator = [1, 2, 3][Symbol.iterator]();
// イテレートする
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
イテレータについて詳しくは「JavaScriptのIteratorとGeneratorを使って反復処理を書く」をご覧ください。
より簡易なイテレータの処理方法として、for-ofがあります。通常はこちらを使います。
// それぞれの値を出力する
for(const value of [1, 2, 3]) {
console.log(value);
}
配列のメソッド
Array.from(arrayLike, mapFn = undefined, thisArg = undefined)
Array.fromはstaticなメソッドで、配列っぽいもの(array-like)およびiterableオブジェクトから新しい配列を作成します。配列のコピーなどに使用できます。
const array = [1, 2, 3];
const clone = Array.from(array); // arrayのコピーを作る
このとき、コピーは浅いコピー(シャローコピー)となり、中のオブジェクト自体は複製されません。あくまでも配列のコピーとなります。
ちなみにスプレッド演算子を使用しても同様のことが実現できます。
const array = [1, 2, 3];
const clone = [...array]; // arrayのコピーを作る
Array.fromが受け付けるのは配列だけでなく、配列っぽいもの(array-like)とiterableなので、例えばNodeListを配列に変換することなども可能です。
const nodeList = document.querySelectorAll('div'); // NodeListを取得
const nodeArray = Array.from(nodeList); // 配列に変換
Array.fromでは、第二引数に関数を入れることで、変換時にmapメソッドを同時にかけることもできます。
// mapメソッドを使って配列に変換(コピー)
const array = Array.from([1, 2, 3], (value) => value * 2);
console.log(array); // [2, 4, 6]
また、第三引数ではmap関数内で使用するthisの値を指定することができます。
Array.isArray(obj)
Array.isArrayは、引数の値が配列かどうかをチェックすることができます。配列ならばtrueを返し、そうでなければfalseを返します。
console.log(Array.isArray([1]); // true
console.log(Array.isArray(2); // false
console.log(Array.isArray('3'); // false
Array.of(element1, element2, …elementN)
Array.ofは引数に与えられた値を持った配列を作成します。newえ配列を作成するときとほぼ同じです。異なるのは、引数がひとつのときの挙動で、Array.ofは引数がひとつでも、その要素を持った配列を作成します。
new Array(3); // [empty, empty, empty]
Array.of(3); // [3]
new Array(1, 2, 3); // [1, 2, 3]
Array.of(1, 2, 3); // [1, 2, 3]
concat(other)
concatは配列同士を結合し、新しい配列を生成するメソッドです。このメソッドは元の配列および引数に与えた配列を変更せず、ただ新しい配列を返します。
const array1 = [1, 2, 3];
const array2 = [4, 5];
const array3 = array1.concat(array2); // [1, 2 , 3, 4, 5]
結合には浅いコピー(シャローコピー)が使われます。
copyWithin(target, start = 0, end = this.length)
copyWithinメソッドは、配列内の一部を、配列内の別の場所にコピーして上書きします。戻り値は配列自身です。
第一引数にコピー先を指定し、第二引数にコピー元の開始地点、第三引数にコピー元の終了地点を指定します。デフォルトでは配列の先頭から末尾までの全てがコピー元になります。範囲はstartを含み、endを含みません。
引数にマイナスの値を指定すると、末尾からの位置になります。
[1, 2, 3, 4, 5].copyWithin(2); // [1, 2, 1, 2, 3]
[1, 2, 3, 4, 5].copyWithin(-1); // [1, 2, 3, 4, 1]
[1, 2, 3, 4, 5].copyWithin(1, 3); // [1, 4, 5, 4, 5]
[1, 2, 3, 4, 5].copyWithin(2, 3, 5); // [1, 2, 4, 5, 5]
コピー時にはみ出た値は破棄されます。
entries()
entriesメソッドは[key, value]ペアを扱うiteratorを返します。
for(const e of [1, 2, 3].entries()) {
// [0, 1]
// [1, 2]
// [2, 3]
console.log(e);
}
for-ofと分割代入を活用すると、key-valueペアを簡単に分離できます。
for(const [key, value] of [1, 2, 3].entries()) {
// key = 0, value = 1
// key = 1, value = 2
// key = 2, value = 3
console.log(key, value);
}
every(testFunc, thisArg = undefined)
everyメソッドはテスト関数を受け取り、配列の要素全てがテスト関数を通過した時にtrueを返し、ひとつでもテストに落ちればfalseを返すメソッドです。
テスト関数は配列の値をひとつ受け取り、trueかfalseを返す関数です。
// 配列の値がすべて偶数かどうか判断する
[2, 4, 6].every((value) => value % 2 === 0); // true
[2, 4, 6, 7].every((value) => value % 2 === 0); // false
また、第二引数で、テスト関数内で使用するthisの値を指定することも可能です。
テスト関数は最大3つの引数を取ります。第2引数は現在の値のインデックスで、第3引数は対象の配列そのものです。
[2, 4, 6].every((value, index, thisArray) => {
console.log(value, index, thisArray);
return value % 2 === 0;
});
fill(value, start = 0, end = this.length)
fillメソッドは配列のstartからendまでのインデックスの値をvalueにします。このときendは含まれません。
[0, 0, 0, 0, 0].fill(1); // [1, 1, 1, 1, 1]
[0, 0, 0, 0, 0].fill(1, 3); // [0, 0, 0, 1, 1]
[0, 0, 0, 0, 0].fill(1, 2, 4); // [0, 0, 1, 1, 0]
startかendにマイナスの値を指定すると、配列の末尾からのインデックスになります。
newで作成した空配列の値を埋めるのにも便利です。
const array = new Array(100); // サイズ100の配列を作成
array.fill(0); // 0で埋める
filter(testFunc, thisArg = undefined)
fileterメソッドはテスト関数をtrueで通過した要素のみを新たな要素とする、新たな配列を返します。元の配列は変更しません。
テスト関数は引数を1つから3つ受け取る関数で、trueかfalseを返します。つまりeveryメソッドのテスト関数と同じです。第1引数に値を、第2引数に値のインデックスを、第3引数に配列そのものを受け取ります。
テスト関数を通してtrueになった要素のみが、新たな配列の要素になります。
// 引数が1つのフィルタ関数
const array = [1, 2, 3, 4, 5].filter((value) => value > 2);
console.log(array); // [3, 4, 5]
// 引数が2つのフィルタ関数
const array = [1, 2, 3, 4, 5].filter((value, index, thisArray) => value > 2);
console.log(array); // [3, 4, 5]
filterメソッドの第2引数には、テスト関数のthisとして使う値を指定できます。
find(testFunc, thisArg = undefined)
findメソッドはテスト関数がtrueになる最初の要素を返します。見つからない場合はundefinedを返します。
[1, 2, 3, 4, 5].find((value) => value > 2); // 3
[1, 2, 3, 4, 5].find((value, index, thisArray) => value > 2); // 3
findメソッドの第2引数にはテスト関数で使うthisの値を指定できます。
findIndex(testFunc, thisArg = undefined)
findIndexメソッドはfindメソッドとほぼ同じですが、こちらは配列の値ではなくインデックスを返します。
[1, 2, 3, 4, 5].findIndex((value) => value % 2 === 0); // 1
[1, 2, 3, 4, 5].findndex((value, index, thisArray) => value % 2 === 0); // 1
第2引数にはテスト関数で使うthisの値を指定できます。
flat(depth = 1)
flatメソッドは配列内の配列を展開して、新しい配列を返します。depthには何段階まで展開するかの深さをしてできます。元の配列は変更しません。
[[1, 2], [3,4]].flat(); // [1, 2, 3, 4]
[[1, 2], [3, [4, 5]]].flat(); // [1, 2, 3, [4, 5]]
[[1, 2], [3, [4, 5]]].flat(2); // [1, 2, 3, 4, 5]
このメソッドは現在Chrome69のみ対応しています。
flatMap(mapFunc, thisArg = undefined)
flatMapメソッドは配列の要素にmapFunc関数を適用した後、その結果を配列内に展開します。
[1, 2, 3].flatMap((value) => [value * 2]); // [2, 4, 6]
[1, 2, 3].flatMap((value) => [value, value * 2]); // [1, 2, 2, 4, 3, 6]
mapFunc関数は最大3つの引数を取ります。
[1, 2, 3].flatMap((value, index, thisArray) => [value]);
このメソッドは現在Chrome69のみ対応しています。
forEach(callback, thisArg = undefined)
forEachメソッドは配列の各要素に対して順番にcallback関数を適用します。戻り値はありません。
for文やfor-ofの代替として使用することができます。
// callback関数の引数がつの場合
[1, 2, 3].forEach((value) => console.log(value));
// callback引数の関数が3つの場合
[1, 2, 3].forEach((value, index, thisArray) => console.log(value));
ただしforEachメソッドはforやfor-ofと比べると著しく遅く、巨大な配列に対して使用すべきではありません。
includes(searchElement, fromIndex = 0)
includesメソッドは配列にsearchElementが含まれている場合はtrueを、そうでない場合はfalseを返します。fromIndexには検索開始位置を指定できます。負の値を与えた場合は、末尾からのインデックスになります。
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(5); // false
[1, 2, 3].includes(2, 2); //false
indexOf(searchElement, fromIndex = 0)
indexOfメソッドは配列のsearchElementのインデックスを返します。存在しない場合は-1を返します。fromIndexには検索開始位置を指定できます。負の値を与えた場合は、末尾からのインデックスになります。
[5, 6, 7].indexOf(6); // 1
[5, 6, 7].indexOf(8); // -1
[5, 6, 7].indexOf(6, 2); // -1
要素の比較には、厳密な比較(===)が使用されます。
join(separator = ‘,’)
joinメソッドは、配列の全ての要素をカンマで繋いだ文字列を返します。separatorを指定することでカンマ以外の区切り文字も使えます。区切り文字を使いたくない場合は、空文字列を渡します。
['a', 'b', 'c'].join(); // 'a,b,c'
['a', 'b', 'c'].join('-'); // 'a-b-c'
['a', 'b', 'c'].join(''); // 'abc'
['a', 'b', 'c'].join('!!!'); // 'a!!!b!!!c'
keys()
keysメソッドは配列のキーを扱うiteratorを返します。配列のキーとは、つまりインデックスのことです。entriesメソッドのキーのみ版と言えます。
for(const key of [12, 15, 17].keys()) {
console.log(key); // 0, 1, 2
}
lastIndexOf(searchElement, fromIndex = this.length – 1)
lastIndexOfは配列を末尾から検索し、searchElementのあるインデックスを返します。見つからない場合は-1を返します。fromIndexを指定すると、fromIndexから逆向きに検索していきます。
[1, 1, 1].lastIndexOf(1); // 2
[1, 1, 1].lastIndexOf(2); // -1
要素の比較には厳密な比較(===)が使用されます。
map(mapFunc, thisArg = undefined)
mapメソッドは、配列の各要素に対してmapFunc関数を適用し、その結果をまとめた配列を新しい配列として返します。元の配列は変更されません。
// mapFunc関数の引数が1つの場合
[1, 2, 3].map((value) => value * 2); // [2, 4, 6]
// mapFunc関数の引数が3つの場合
[1, 2, 3].map((value, index, thisArray) => value * 2);
pop()
popメソッドは配列の最後の要素を取り出して返し、配列から削除します。配列が空の場合はundefinedを返します。
const array = [1, 2, 3];
const popped = array.pop();
console.log(array); // [1, 2]
console.log(popped); // 3
push(element1, element2, …elementN)
pushメソッドは配列の末尾に新しくelementを追加し、要素を追加後のlengthを返します。
const array = [1, 2, 3];
array.push(4);
console.log(array); // [1, 2, 3, 4]
array.push(5, 6);
console.log(array); // [1, 2, 3, 4, 5, 6]
このメソッドはスプレッド演算子による配列の展開とも相性が良く、別の配列の値を個別にpushすることもできます。
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
array1.push(...array2);
console.log(array); // [1, 2, 3, 4, 5, 6]
reduce(callback, initialValue = this[0])
reduceメソッドは、配列の値に対してinitialValueを初期値として、左から右に次々とcallback関数を適用していき、ひとつの値にまとめて返します。元の配列は変更されません。
initialValueが指定されたときは、initialValueを初期値として、最初の要素から処理が開始されます。initialValueに初期値を指定しないときは、配列の最初の値をinitialValueとして、2番目の要素から処理を開始します。
この複雑なメソッドを理解するための第一歩は「配列の総和」です。配列の各要素を次々と足していき、総和を求めます。
// prev = 5, current = 10から開始
// つまり5 + 10 + 20の計算ができる
[5, 10, 20].reduce((prev, current) => prev + current); // 35
このときcallback関数は2つの引数を取ります。ひとつめはprevで、callback関数が前の実行時に返した値がここに入ります。まだ初めの実行のときは、initialvalueが入ります。
ふたつめはcurrentで、配列の左から順番に、現在の値が入ります。今回はinitialValueが未指定なので、2番目の要素(つまり「10」)から始まります。
このとき「10」に対してcallback関数を実行し、prev + currentで、5 + 10を計算して「15」を返しています。この「15」が次のcallback実行時のprevになります。
次に3番目の要素「20」に対してcallback関数を実行し、prevは「15」でcurrentは「20」です。ここでprev + currentを返すので、「35」です。これで配列の最後まで行ったのでこれを最終結果とし、このメソッドの戻り値は「35」となります。
また、initialValueを指定すれば、その値をベースに計算ができます。
// 100 + 5 + 10 + 20
[5, 10, 20].reduce((prev, current) => prev + current, 100);
initialValueやcallback関数の戻り値は数値である必要はなく、オブジェクトなどでも実行可能です。
また、callback関数は最大4つまでの引数を取ります。
[5, 10, 20].reduce((prev, current, index, thisArray) => prev + current);
reduceRight(callback, initialValue = this[this.length – 1])
reduceRightメソッドは右から左に向けてreduceします。使い方はreduceメソッドと同じです。
// 20 + 10 + 5
[5, 10, 20].reduceRight((prev, current) => prev + current);
reverse()
reverseメソッドは配列を反転させ、反転させた配列を返します。このメソッドは元の配列を変更します。
[1, 2, 3].reverse(); // [3, 2, 1]
shift()
shiftメソッドは配列から最初の値を取り出し、返します。popメソッドは最後の値を取り出しましたが、shiftメソッドは最初の値を取り出します。配列が空の場合はundefinedを返します。
const array = [1, 2, 3];
const shifted = array.shift();
console.log(array); // [2, 3]
console.log(shifted); // 1
slice(begin = 0, end = this.length)
sliceメソッドは配列の一部(beginからendまで)を切り出し、新しい配列として返します。endの値は含めず、endの直前までを切り出します。
[1, 2, 3, 4, 5].slice(3); // [4, 5]
[1, 2, 3, 4, 5].slice(2, 4); // [3, 4]
[1, 2, 3, 4, 5].slice(-3); // [3, 4, 5]
startおよびendにマイナスの値を指定すると、配列の最後からのインデックスとして扱われます。
some(testFunc, thisArg = undefined)
someメソッドは配列の要素の最低ひとつでもテスト関数に合格するならtrueを、ひとつも合格しないならfalseを返します。テスト関数はtrueかfalseを返す関数です。
このメソッドはeveryメソッドと似ていますが、everyメソッドは全ての要素が合格しないといけないのに対し、someメソッドはひとつでも合格すればtrueになります。
testFunc関数は最大3つの引数を取ります。
// testFunc関数の引数が1つの場合
[1, 2, 3].some((value) => value % 2 === 0); // true
[1, 2, 3].some((value) => value % 5 === 0); // false
// testFunc関数の引数が3つの場合
[1, 2, 3].some((value, index, thisArray) => value % 2 === 0);
また、余談ですが、このsomeメソッドを配列のイテレーションに使うことを推奨する劣悪な資料がネット上にはあります。someメソッドはあくまでも配列の要素がテスト関数を満たすかどうかをチェックするためのメソッドであり、イテレーションのためのメソッドではありません。単純なイテレーションの場合はfor、for-of、forEachメソッドなどを使用してください。
sort(compareFunc = undefined)
配列を文字列の辞書順でソートし、ソートした配列を返します。このメソッドは元の配列を変更します。
compareFuncに任意の比較関数を渡すことで、ソートの挙動を変更できます。compareFuncは負数、0、正の数のいずれかを返します。
- comapreFunc(a, b)が負数(-1など)を返した場合、aはbより先に来ます
- compareFunc(a, b)が0を返した場合、aとbは同じ値です
- compareFunc(a, b)が正の数(1など)を返した場合、bがaより先に来ます
単純な数値順ソートをしたい場合、a – bまたはb – aを計算する関数を渡せば実現できます。
[5, 7, 2, 6, 1, 9].sort((a, b) => a - b); // [1, 2, 5, 6, 7, 9]
[5, 7, 2, 6, 1, 9].sort((a, b) => b - a); // [9, 6, 7, 5, 2, 1]
compareFuncを指定しない場合は、辞書順ソートとなるため、たとえば「70」は「8」より前に来ます。
splice(index, howMany, element1 = undefined, …elementN = undefined)
spliceメソッドは、配列の中から要素を取り除きます。また、取り除いた後に要素を付け加えることも可能です。このメソッドは元の配列を変更します。
// 3番目の要素から1個削除する(=3番目の要素を削除する)
const array1 = [1, 2, 3, 4]
const deleted1 = array1.splice(2, 1);
console.log(array1); // [1, 2, 4]
console.log(deleted1); // [3]
// 3番目の要素から2個削除して、10と20を加える
const array2 = [1, 2, 3, 4]
const deleted2 = array2.splice(2, 2);
console.log(array2); // [1, 2, 10, 20]
console.log(deleted2); // [3, 4]
Arrayには「remove」のようなメソッドがないため、特定要素を取り除くためにもspliceはよく使用されます。
const array = [1, 2, 3, 4];
const deleteIndex = array.indexOf(3); // 「3」のインデックスを探す
array.splice(deleteIndex, 1); // 「3」を削除する
toLocaleString()
toLocaleStringメソッドは配列をロケール固有の文字列に変換して返します。
例えば日本ならば数字にカンマがついたりします。
[10000, 20000].toLocaleString(); // '10,000,20,000'
内部処理としては、各要素のtoLocaleStringメソッドを呼び出しています。
toString()
toStringメソッドは配列を文字列に変換して返します。
[10000, 20000].toString(); // '10000,20000'
配列の各要素をカンマで繋いで返します。
unshift(element1, element2, …elementN)
unshiftメソッドは配列の最初に要素を追加し、追加後の配列の長さを返します。このメソッドは元の配列を変更します。
const array = [1, 2, 3];
array.unshift(0);
console.log(array); // [0, 1, 2, 3]
values()
valuesメソッドは配列の各値を扱うiteratorを返します。
for(const value of [1, 2, 3].values()) {
console.log(value);
}
// 以下と同じ
for(const value of [1, 2, 3]) {
console.log(value);
}