配列の中身を forEach() を使ってループし、途中で結果を返そうとしたところ、思うように結果を返せず沼ってしまいました。これまで「楽に書ける」という理由から forEach() を利用していましたが、return でも処理を終わらせられない発見があったので、forEach() についてまとめてみました。
【結論】forEach() は繰り返し途中で処理を終わることができない
forEach() で繰り返し処理をしている間は、たとえ return や break の処理を実行したとしても、処理が終了することはありません。要素の数だけ実行されて初めて処理が終了します。

forEach() で繰り返したの過程を見ると、最後に true が返っているにも関わらず、メソッドの戻り値は false が返っていました。この挙動を知らずに実装すると大変なことになってしまう。
forEach の使い方
配列に対して forEach() を使うことで、要素分だけ処理を繰り返すことができます。繰り返し処理にはいくつか書き方がありますが、forEach() を使うメリットとして、書くコードの量が少なく見やすいことが挙げられるでしょう。
今回は GAS を使って forEach() の処理結果を確認してみました。
spreadsheet にサンプルデータ「2022/12/26〜2023/1/1」1週間分の日付を用意。

これを forEach() を用いて一覧表示させてみます。

配列に入った日付データを7つ表示できました。
シンプルな使い方で、かつ配列の要素数も考慮せずに使えるのは便利ですね!
繰り返し処理の途中で return を返してみる
先ほどの処理に条件分岐を追加し、途中で処理が終わるように手を加えます。
元日かどうか判断するメソッドに書き換え、1週間のうち「2023年1月1日」があれば、true を返し。それ以外の日付では false を返すようにしました。

サンプルデータには「2023年1月1日」があるため、本来は true が返ってきて欲しいところでしたが、boolean 変数の中身を確認すると false が入っていました。
false が返る理由として条件分岐のときに true を通ってない、つまり上手く条件分岐できていない可能性も考えられます。そのため 他の処理は変更せず、forEach() を for文に置き換えて、検証してみました。
同じように false が返ってきた場合は条件分岐ができてないと言えるはずです。

for文の繰り返し処理の結果、 true が返ってきました。ということは、「2023年1月1日」のデータのときに true の処理に通っており、条件分岐に問題はなかったと言えます。
forEach() と for文の違いで「true が返るのか」「false が返るのか」結果が変わっていました。
処理過程も確認してみる
結果だけを見ると不思議ですが、その処理過程をログで確認すると、forEach() と for文の違いは一目瞭然でした!

forEach() では「2023年1月1日」のときに true の処理が通るものの、そこで終了することなく行27まで実行されました。そのため true が false へ更新され、変数の中身は false でした。

一方、for文を確認すると、こちらも「2023年1月1日」のとき true の処理が通るのは一緒でした。その後に違いがあり、for文の場合は行24で処理が終了され、false へと更新されることはありません。
結果として、変数には true が入っていました。
繰り返し途中で処理を終わらせたいなら、forEach() は使ってはならない
forEach() と for文の違いを見てきたとおり、forEach() は return を通ったとしても処理が終了されることはありません。私は return に通ると、必ずメソッドの処理が終了するとばかり思っていたため、この例外に気づいたとき衝撃でした。
繰り返しの書き方を1つ選ぶのにも挙動の違いがあり、プログラムの奥深さを改めて思い知らされました。
この forEach() の挙動は言語によって異なることもないそうで、今回は JavaScript で処理を書いていましたが、Java や PHP でも同じ結果になると考えられます。興味ある方は一度試してみてください!