👋
【javascript】foreach文でcontinueやbreak
はじめに
何年かjavascriptを触っていながら、foreach文の仕様に気づいていなく、つい先日ようやく壁にぶち当たることがあったので、メモ。
内容
foreach文について今一度整理してみる。
「任意の配列の要素に対して、与えられたコールバック関数を順番に実行していくための構文」であり、具体的には以下のような挙動をする。
forEachについて
let array1 = ["111", "222", "333", "444"];
array1.forEach((elm) => {
// 要素を出力
console.log(elm);
});
// 111
// 222
// 333
// 444
// こんな書き方でもOK
array1.forEach(function(elm){
// 要素を出力
console.log(elm);
});
このforEach文は、通常のループとは違いcontinueやbreakができない。(ちゃんと考えれば、forやwhileのように処理をループしているのではなく、関数を順番に実行しているだけなので出来ないのは当たり前なのだが)
詳細
ではどうすればcontinueやbreakのように途中で処理を中断したりループから抜け出せばよいか。
まずcontinueについて。関数を実行→関数が終了したら次の関数実行→。。。のように続いているので、関数を強制終了させてしまえばよい。
forEachでcontinue
let array1 = ["111", "222", "333", "444"];
array1.foreach((elm) => {
if(elm === "333"){
// 処理を中断
return;
}
// 要素を出力
console.log(elm);
});
// 111
// 222
// 444
これで問題なくcontinueできます。
では、breakはどうか。結論から言うと「breakする可能性があるならfor-inやfor-ofを使う」となる。
forEachの仕組み上breakするのは不可能なので、どうしてもそのような挙動をさせたいならforEachではなくsome関数などで代替する、となってしまい、「forEachでbreakする」からずれてしまうし、代替案としてあげられるものはほとんどがテスト用のメソッドだからである。
(参考記事↓)
まとめ
多少駆け足になってしまったが、まとめると以下のようになる。
- forEachでcontinue → return
- forEachでbreak → some関数などで代用、もしくはfor-in、for-ofの使用
Discussion
あらためてさっと調べてみたのですが、世の中の情報では、本当に大事なことを見つけるのってすごい苦労しますね。
いくつかのサイトみても今更forとかfor inとかを紹介していたり、forの代わりにsomeとかfindとか紹介していて何の意味があるのかと思います。
重要なことと重要でないことが明確に書かれていないので、重要なものを見分けるのが難しいです。
forのところで何が重要かというと、
長年やってて知っていて、ベテランの人は皆知っていると思うのですが、
for系の処理はfor of が一番優れているというか、for of で全部統一できるので、forEachとfor in はまず使わないので理解する価値がないってことです。
forで書くべきところに、someなどを持ち込むのもいろいろつらいでしょう。
配列でindexが必要なときは次のように書きますし
for (const [index, value] of array1.entries()) {...}
オブジェクトのキーでのループも次のようにかけます。
for (const [key, value] of Object.entries(object1)) {...}
continueもbreakも素直にかけます。可読性が高いですし、仕様変更でループをbreakしなければいけなくなった場合も修正が容易です。
forループをforEachで書いたりしていると、それはもうちょっとJavaScriptに詳しくないレベルの技術者だなと思っていいと思います。
重要なことは、for of だけ使うということです。
コメントありがとうございます。
私も基本的には(誰が見ても読みやすいという意図もあり)forを使っていたのですが、勉強も兼ねてforEachを使ってみようと思い手を出したのですが、こんな落とし穴があるとは思いませんでした。
局所的に使うことはあれど、やはり基本的にはfor(for-of)で問題ないようですね。