forEach()のドキュメントは意味不明すぎる【Day28 of 100】

公式ドキュメントページが何たるかはわかってきた

ここにforEach()関数のすべて?が掲載されているみたい。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#for_%E3%83%AB%E3%83%BC%E3%83%97%E3%81%8B%E3%82%89_foreach_%E3%81%B8%E3%81%AE%E5%A4%89%E6%8F%9B

またもや意味不明領域、、、

        // ここから別物
        const ratings = [5, 4, 5];
        let sum = 0;

        const sumFunction = async (a, b) => a + b;

        ratings.forEach(async (rating) => {
          sum = await sumFunction(sum, rating);
        });

        console.log(sum);
        // 本来期待される出力: 14
        // 実際の出力: 0

意味わからんにAIくんの意味はうっすら分かる解説

これはJavaScriptの**非同期処理(async/await)**と、forEachの仕様が組み合わさった時に非常によく起こる「落とし穴」ですね。

結論から言うと、forEachは「待ってくれない」からです。


なぜ 14 にならないのか?

  1. forEach は投げっぱなし:forEach は、中の関数が async(非同期)であっても、その完了を待たずに次のループへ進み、さらにその後の処理(console.log)を実行してしまいます。
  2. 実行のタイミング:sumFunction が計算を終えて結果を返す前に、JavaScriptは一番下の console.log(sum) を実行してしまいます。その時点ではまだ sum は初期値の 0 のままなので、 0 が表示されます。

どうすれば解決できる?

非同期処理を順番に待ちたい(同期させたい)場合は、forEach ではなく for...of ループ を使うのが最も一般的なショートハンド的な解決策です。

修正コード:for...of を使う

JavaScript

const ratings = [5, 4, 5];
let sum = 0;

const sumFunction = async (a, b) => a + b;

// 非同期の文脈(async関数内など)で実行する必要があります
const calculate = async () => {
  for (const rating of ratings) {
    sum = await sumFunction(sum, rating); // ここでちゃんと待機する
  }
  console.log(sum); // 出力: 14
};

calculate();

もう一つの解決策:reduce を使う(上級編)

配列の値を一つにまとめたい場合、reduce を使うのがプロっぽい書き方です。ただし、非同期が絡むと少し複雑になります。

JavaScript

const total = await ratings.reduce(async (accPromise, rating) => {
  const acc = await accPromise;
  return await sumFunction(acc, rating);
}, Promise.resolve(0));

console.log(total); // 出力: 14

まとめ

  • forEach は**「並列でどんどん実行して、終わりを待たない」**時に使う。
  • await を使って順番に処理したいなら for...of を使う。

「非同期処理」はJavaScriptの中でも少しややこしい部分ですが、ここをマスターすると一気に書けることの幅が広がります。

この for...of の書き方について、もっと詳しく知りたい部分はありますか?

分からん!けど100日後もしくは365日後には分かるはず

さっぱり分からん。けどうっっっっすら分かった、覚えたことがある

  • forEach()は配列を拾い出すためのもの。配列が対象
  • 同期処理(ピタゴラスイッチ)ではなく非同期処理(待ってくれないJavaScriptの処理)
  • forEach()が読みたいコードに出てきたら悩んだ後AIに翻訳してもらおう
  • ここでもアロー関数が出現。アロー関数が頭に100%馴染んでないからそこで解読ストップしちゃう


コメントを残す

猫でデザインとプログラミングを学ぶをもっと見る

今すぐ購読し、続きを読んで、すべてのアーカイブにアクセスしましょう。

続きを読む