JavaScriptのforEachの使い方、for-ofループとの違い、MapとSetとの組み合わせ

2021年2月9日JavaScript

JavaScriptのforEachの使い方とfor-ofループとの違いをまとめました。
また、forEachとmapとsetとの組み合わせ方も紹介します。

for-ofループの使い方については、次の記事を参考にしてみてください。

forEach()の使い方

forEachは、配列のメソッドで、第一引数に値、第二引数にインデックス、第三引数に配列自体をとります。
forEach()を使うと、配列のそれぞれの内容を簡単に取り出すことができます。
for文という繰り返しをeach(個々の)なので、要素がなくなるまで、それぞれの要素ごとに繰り返すという処理ができます。

具体的な書き方は次の通りです。

要素を取り出したい配列名.forEach((値,インデックス,配列) => {
処理内容;
});

第二引数、第三引数は省略して書くことも多いです。
なお、第一引数について、名前は自由につけることができますが、取り出した値を入れるための引数に配列の単数形を使うとわかりやすいです。

 'use strict';
{
  const testScores = [50, 40, 60];

  testScores.forEach((testScore) => {
    console.log(`テスト結果: ${testScore}点です。`);
  });

}

インデックスを表示したい場合、2つ目の引数を設定します。
そうすると、2つ目にインデックス番号を入れることができます。
名前は自由に決められます。
今回はtestとしてみましょう。次のようになります。

 'use strict';
  {
    const testScores = [50, 40, 60];
  
    testScores.forEach((testScore, test) => {
      console.log(`テスト教科 ${test}番: ${testScore}点です。`);
    });
  
  }

forEachで値を取得する

比較のために、同じことができるfor-ofループも記載します。

 {
  const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];

//for-ofループ
  for (const movement of movements) {
    if (movement > 0) {
      console.log(`${movement}を入金します。`);
    } else {
      console.log(`${Math.abs(movement)}を引き出します。`);
      //Math.absはabsolute、つまり絶対値を取り出してくれるメソッドです。
    }
  }
  /*
200を入金します。
450を入金します。
400を引き出します。
3000を入金します。
650を引き出します。
130を引き出します。
70を入金します。
1300を入金します。
*/

//forEach
  movements.forEach(function (movement) {
    if (movement > 0) {
      console.log(`${movement}を入金します。`);
    } else {
      console.log(`${Math.abs(movement)}を引き出します。`);
      //Math.absはabsolute、つまり絶対値を取り出してくれるメソッドです。
    }
  });
  /*
200を入金します。
450を入金します。
400を引き出します。
3000を入金します。
650を引き出します。
130を引き出します。
70を入金します。
1300を入金します。
*/
}

forEach()は高階関数で、その引数にコールバック関数をとります。
forEachがその内部関数の実行を指示するわけです。
そして、forEachは引数をとることができます。
0: function(200)
1: function(-450)
2: function(400)…という感じでループが終わるまで一つずつ実行されます。
そして、中身は上のfor-ofループとまったく同じものをいれます。

forEachでキーと値を取得する

比較のために、同じことができるfor-ofループも記載します。

 {
//for-ofループ
  const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];

  for (const [i, movement] of movements.entries()) {
    if (movement > 0) {
      console.log(`${i + 1}回目:${movement}を入金します。`);
    } else {
      console.log(`${i + 1}回目:${Math.abs(movement)}を引き出します。`);
      //Math.absはabsolute、つまり絶対値を取り出してくれるメソッドです。
    }
  }
  /*
1回目:200を入金します。
2回目:450を入金します。
3回目:400を引き出します。
4回目:3000を入金します。
5回目:650を引き出します。
6回目:130を引き出します。
7回目:70を入金します。
8回目:1300を入金します。
  */

//forEach
  movements.forEach(function (movement, index, array) {
    if (movement > 0) {
      console.log(`${index + 1}回目:${movement}を入金します。`);
    } else {
      console.log(`${index + 1}回目:${Math.abs(movement)}を引き出します。`);
      //Math.absはabsolute、つまり絶対値を取り出してくれるメソッドです。
    }
  });
  /*
1回目:200を入金します。
2回目:450を入金します。
3回目:400を引き出します。
4回目:3000を入金します。
5回目:650を引き出します。
6回目:130を引き出します。
7回目:70を入金します。
8回目:1300を入金します。
  */
}

forEachに引数名は自由に決められます。
ただし、順番は重要になります。
第一引数はcurrent element, 第二引数はcurrent index, 第三引数はループさせる配列と決まっています。

for-ofループとforEachのどちらを使うべきか

このように、インデックス番号を取得したい場合、for-ofループは、Object.entries()メソッドを使う必要があります。
この点を考えるとforEachの方がシンプルでわかりやすいでしょう。

しかし、forEachはfor-ofループとは異なり、breakもcontinueも使えません。
後は好みの問題となります。
Object.entries()メソッドについては、次の記事を参考にしてみてください。

forEachとMapの組み合わせ

 {


  const money = new Map([
    ['USD', 'United States dollar'],
    ['EUR', 'Euro'],
    ['GBP', 'Pound sterling'],
  ]);

money.forEach(function(value, key, map) {
  console.log(`${key}: ${value}`);
});
/*
USD: United States dollar
EUR: Euro
GBP: Pound sterling
*/

}

forEachとMapを使うとき、第一引数に値、第二引数にキー、第三引数にmap全体をとります。
Mapの使い方は、こちらの記事を参考にしてみてください。

forEachとSetの組み合わせ

 {

  const moneyUnique = new Set(['USD', 'JPY', 'EUR', 'JPY']);

    console.log(moneyUnique);
    moneyUnique.forEach(function(value, key, map) {//間違い!!
  console.log(`${key}: ${value}`);
});
/*
USD: USD
JPY: JPY
EUR: EUR
*/

}

forEachとsetをmapと同じように使用してみると、下のような結果が返ってきます。
USD: USD
JPY: JPY
EUR: EUR
これは、keyとvalueが全く同じ値として返されています。
それは、Setはキーもインデックス番号もないためです。
そのため第二引数以降は設定せずにつかいましょう。
Setの使い方は、こちらの記事を参考にしてみてください。