質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

4回答

1458閲覧

JavaScriptでのfor、forEachループ内での処理の止め方がわからない

span

総合スコア32

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/02/28 18:23

javascript

1 let data = [1, 2, 3, 4, 5, 6, 7] 2 3 data.forEach((res) => { 4 if (res == 4) { 5 return 6 } 7 }) 8 console.log('hogehuga')

javascript

1 let data = [1, 2, 3, 4, 5, 6, 7] 2 for (let i in data) { 3 if (i === 4) { 4 return 5 } 6 } 7 console.log('hogehuga')

上記のようなケースでconsole.log('hogehuga')を通ることなく処理を止めたいのですがうまくいきません。

javascript

1 let data = [1, 2, 3, 4, 5, 6, 7] 2 let test = true 3 4 data.forEach((res) => { 5 if (res == 4) { 6 test = false 7 return 8 } 9 }) 10 if (test) { 11 console.log('hogehuga') 12 }

上記のようなループの中でフラグを持たせてconsole.log('hogehuga')の出し分けをするようなやり方ではなく早期returnで処理を止める方法はないのでしょうか?
このようなケースのベストプラクティスをご教示いただければ幸いです。申し訳ありませんがよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

こんにちは

stackoverflow の質問「Short circuit Array.forEach like calling break 」に対するこの回答にあるように、try...catch を使うか、some を使うのがよいかと思います。

以下は上記2つの方法を、ご質問にあるコードに適用したサンプルです。(returnで抜けたい関数を f()としました。)

1. try ... catch を使う

javascript

1function f(data) { 2 try { 3 data.forEach((res) => { 4 if (res == 4) { 5 throw "four is found." 6 } 7 }) 8 } catch(e) { 9 return 10 } 11 12 console.log('hogehuga', data) 13} 14 15 16f([1, 2, 3, 5, 6, 7]) // => "hogehuga" [1, 2, 3, 5, 6, 7] が出力される。 17 18f([1, 2, 3, 4, 5, 6, 7]) // => 何も出力されない。 19

2.some を使う

こちらは、ご質問にあるコードのうち、 test に 4 があるかどうかの結果を入れるコードに近いです。forEachを使った場合との違いは、someを使うと4が見つかった時点でそれ以降の要素については調べないで、すぐ結果を返してくれることです。

javascript

1function f(data) { 2 // data の要素を先頭から調べて、4があったらすぐループを抜けて、test はtrueになり、4がなければfalseになる。 3 const test = data.some( 4 (res) => { 5 return (res == 4) 6 } 7 ) 8 9 if (!test) { 10 console.log('hogehuga', data) 11 } 12} 13 14 15f([1, 2, 3, 5, 6, 7]) // => "hogehuga" [1, 2, 3, 5, 6, 7] が出力される。 16 17 18f([1, 2, 3, 4, 5, 6, 7]) // => 何も出力されない。 19

someを使うほうは、Qiita にも同様の投稿がありました。

以上、参考になれば幸いです。

投稿2020/02/28 22:23

編集2020/02/29 01:25
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oikashinoa

2020/02/29 04:18

>マイナスした人へ なんで-1なんでしょうか? ループを打ち切りたい→後続の処理を飛ばすことで早く処理を終わらせたい→try ... catchだとかえって遅くね?ってところなんですかね。 それならjsPerfなどで速度測定してから反論して欲しいです…
jun68ykt

2020/02/29 05:35

@oikashinoaさん コメントありがとうございます。 そうですね。ぜひ私も理由をご教示頂きたいと思っております。 ひとつ想像できるのは、回答に挙げたstackoverflow の質問への回答に対するコメントの中で、 Exception handling should NEVER be used as control flow. PERIOD. – frank Nov 10 '17 at 23:00 というコメントがあります。翻訳すると、「例外をフロー制御に使うべきじゃない。以上」という感じでしょうか。確かに、特に何かエラーが起きたわけでもないのに、例外をthrowするのはしっくりこないという風に感じる人もいらっしゃるだろうなとは思います。
oikashinoa

2020/02/29 05:46

> 「例外をフロー制御に使うべきじゃない。以上」 そこは同意ですね。別の機会でソース読むときにTry...Catchされたら?になります。(コメント書いてあってもやだな。バグや想定外の動きが有った場合も気づかないし) 1. try ... catch を使う には注記を書いたほうが良いと思います。
guest

0

forEach()だと難しいですが、Array.prototype.some()またはArray.prototype.every()を使うと失敗または成功時にその場でreturnっぽいことはできます。下記はsome()を使った例です。

JavaScript

1const f = () => { 2 let data = [1, 2, 3, 4, 5, 6, 7] 3 4 if (data.some((res) => { 5 console.log(res) // => 1, 2, 3, 4まで 6 if (res == 4) { 7 return true 8 } 9 return false 10 })) return 11 console.log('hogehuga') 12}

ただ、いいコードかどうかはちょっと微妙です。

投稿2020/02/28 22:22

raccy

総合スコア21754

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

Array.forEach()は、「配列内の要素それぞれを引数に取って関数を実行する」というArrayのメソッドであり、ループとはちょっと違います。なので途中でやめたりはできません。

途中でやめたいなら普通にforループでbreakするべきでしょう。ちなみにfor...inはindexのループ、for...ofはvalueのループになります。
for...inでは順番が保証されない可能性があるので、このような配列の順番が重要なループでは普通のforかfor...ofを使うべきでしょう。

javascript

1for (const d of data) { 2 if (d === 4) break; 3 console.log(d); 4} 5console.log('finish');

これで出力は

1 2 3 finish

になるはずです。

Array.forEachでのreturnは、「その関数を終了させる = 次の要素について実行」なので、普通のループで言うところのcontinueの挙動になりますね。
1個目のコードではvalueが4以外でifの先が実行されます。(ありませんが)
もし

javascript

1data.forEach((res) => { 2 if (res == 4) return; 3 console.log(res); 4}) ; 5console.log('hogehuga');

としたら
出力は

javascript

11 22 33 45 56 6hogehuga

です。
2個目のは、returnしたら関数が終わってしまうのでhogehugaは出力されませんね。またfor...inなのでvalueではなくindexを見てます。保証されませんがもしindexが昇順に参照できたとしたら、同じくif後にdata[i]を出力した場合出力は次のようになります。

javascript

11 22 33 44

投稿2020/02/28 19:41

編集2020/02/28 19:47
kairi003

総合スコア1332

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

span

2020/03/01 17:02

ありがとうございます!大変参考になりました!
guest

0

forEachは思いつかない。

js

1(_=>{ 2 let data = [1, 2, 3, 4, 5, 6, 7] 3 for (let i in data) { 4 if (i == 4) { // for in なら文字列 5 return // 関数内でないと。 6 } 7 } 8 console.log('hogehuga') 9})() 10```**動くサンプル:**[https://jsfiddle.net/9qfc8rhu/](https://jsfiddle.net/9qfc8rhu/)

投稿2020/02/28 18:34

kei344

総合スコア69625

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

span

2020/02/28 18:48 編集

ご回答ありがとうございます、関数ないでないと。の部分がよくわからないのですが関数の場合と関数でない場合では挙動が変わってくるのでしょうか?
span

2020/02/28 18:51

ちなみに関数内での使用を想定しております。申し訳ありませんがご教示頂けると幸いです。
kei344

2020/02/29 02:08

> 関数の場合と関数でない場合では挙動が変わってくるのでしょうか? 単純に、関数外ではreturnが使えません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問