【JavaScript】forEach – 配列の各要素に対して繰り返し処理を行う

JavaScriptの配列操作メソッドの中で、forEach()は配列の各要素に対して繰り返し処理を行うために便利です。今回は、forEach()の基本的な使い方から注意点までをまとめていきたいと思います。

forEach()メソッドとは?

forEach()メソッドは、配列の各要素に対して指定した関数を順番に実行するためのメソッドです。元の配列は変更されません。

基本的な使い方

JavaScript
// 数値の配列を定義
let numbers = [1, 2, 3, 4, 5];

// 各要素をコンソールに出力
numbers.forEach(num => console.log(num));
// 1
// 2
// 3
// 4
// 5

サンプルコード

配列内の要素を処理する

配列の各要素に処理を適用することができます。

JavaScript
let sweets = ['cookie', 'cake', 'chocolate'];

// 各スイーツの名前を大文字に変換して出力
sweets.forEach(sweets => console.log(sweets.toUpperCase()));
// "COOKIE"
// "CAKE"
// "CHOCOLATE"

配列の要素を累積計算する

配列の値を累積計算することも可能です。

JavaScript
let prices = [100, 200, 300];
let total = 0;

// 各価格を合計する
prices.forEach(price => {
    total += price;
});

console.log(`合計金額: ${total}円`); // 合計金額: 600円

HTML要素を変更する

forEach()を使って、HTML要素を動的に変更できます。

JavaScript
// 全てのボタン要素を取得
let buttons = document.querySelectorAll('button');

// 各ボタンの背景色を変更
buttons.forEach(button => {
    button.style.backgroundColor = 'blue';
});

使用時の注意点

breakやreturnでループを中断できない

forEach()のコールバック関数内でreturnを使っても、ループを途中で中断することはできません。
また、breakを使うと構文エラーになります。

JavaScript
let numbers = [1, 2, 3, 4, 5];
numbers.forEach(num => {
    if (num === 3) {
        return; // ここでの return は forEach のコールバック関数内だけに影響する
    }
    console.log(num);
});

// 1
// 2
// 4
// 5

num === 3のときreturnしますが、これは forEach()のコールバック関数内だけで有効です。つまり、現在のループの1回分の処理をスキップするだけで、ループ全体は続行されます。そのため、3はスキップされますが、45は処理されます。

正しくループを途中で終了するには?

代替方法として for…ofを使用します。

JavaScript
for (let num of numbers) {
  if (num === 3) {
      break; // 3 の時点でループを完全に終了
  }
  console.log(num);
}

// 1
// 2

非同期処理には向いていない

forEach()は非同期処理と組み合わせると意図しない動作をすることがあります。

JavaScript
let urls = ['url1', 'url2', 'url3'];

urls.forEach(async url => {
    let response = await fetch(url);
    console.log(await response.text());
});
  • forEach()同期的に処理を進めるため、awaitを使っても待機しません。
  • fetchリクエストが並行して発生しますが、順番が保証されません。
  • forEachはPromiseを返さないため、処理が完了した後に何かをするのが難しい。

複数のリクエストを並行処理したい場合

map()Promise.all()を組み合わせるのが推奨されます。

JavaScript
async function fetchAllUrls() {
  let responses = await Promise.all(urls.map(url => fetch(url).then(res => res.text())));
  console.log(responses);
}

fetchAllUrls();
  • Promise.all()により、全てのリクエストが並列で実行され、すべて完了したらresponsesにまとめて格納される。
  • forEach()ではなくmap()を使うことで Promise の処理を適切に制御できます。

さいごに

forEach()は配列の各要素に対して繰り返し処理を行う便利なメソッドです。ただし、以下の点に注意しましょう。

  • forEach()は元の配列を変更せず、新しい配列を返しません。
  • breakreturnでループを中断できません。
  • 非同期処理にはPromise.all()を活用しましょう。