Menu
日本語

JavaScript for文の使い方|break・continue・配列ループ

JavaScriptのfor文の基本構文から、配列のループ、break・continue、ネストしたループ、無限ループの回避まで実例つきで解説します。

古典的な for 文の書き方

「何回繰り返すか」がはっきり決まっているときに使うのが、JavaScript の for 文です。カウンタを使ったループに必要な3つの要素——初期化継続条件更新処理——を、1行のヘッダーにまとめて書けるのが特徴です。

index.js
Output
Click Run to see the output here.

5回繰り返して、出力も5行。ヘッダー部分を順番に見ていきましょう。

  • let i = 0 はループが始まる前に1回だけ実行されます。カウンタの初期化ですね。
  • i < 5 は毎回のループの前にチェックされます。true なら本体が動き、false ならループは終了します。
  • i++ は本体の処理が終わったあと、次の条件チェックの直前に実行されます。

この3つはカンマではなくセミコロンで区切ります。どれも省略は可能ですが、実際に省くケースは少なく、その場合はたいてい while を使うことになります。

各パーツの動き方を押さえる

順序をしっかり理解するには、一度手で追いかけてみるのが一番です。

index.js
Output
Click Run to see the output here.

順番に追いかけてみましょう。

  1. let i = 1 — カウンタ変数を作って 1 を代入。
  2. i <= 3 を判定 — true なので本体を実行。1 を出力。
  3. i++ を実行 — i は 2 に。
  4. i <= 3 を判定 — true。2 を出力。
  5. i++ を実行 — i は 3 に。
  6. i <= 3 を判定 — true。3 を出力。
  7. i++ を実行 — i は 4 に。
  8. i <= 3 を判定 — false。ループを抜ける。

ポイントは、更新式が本体の ではなく に走るということ。ここで勘違いする人が意外と多いんです。

for文で配列をインデックス指定で回す

for ループの出番として一番多いのが、配列を順番に処理するケースです。このときカウンタ変数がそのままインデックスとして使えます。

index.js
Output
Click Run to see the output here.

いくつか押さえておきたいポイントがあります。

  • 配列のインデックスは0から始まります。最初の要素は 0、最後は length - 1 です。
  • 条件は i <= fruits.length ではなく i < fruits.length です。<= にしてしまうと最後を1つ超えてしまい、undefined が出力されます。
  • ilet で宣言しているので、スコープはループ内だけ。ループの外では参照できません。

インデックスが不要で値だけ取りたいときは、for...of のほうがシンプルで読みやすいです。これは別のドキュメントで詳しく扱います。

break:途中でループを抜ける

break を使うと、その時点でループを即座に終了できます。目的のものが見つかってそれ以上回す必要がない、というようなケースで便利です。

index.js
Output
Click Run to see the output here.

break が実行された瞬間、制御はループの閉じ括弧の外へ飛び出します。更新式も動かず、条件式も再評価されません。ループはそこで終了です。

continue:今回の繰り返しだけスキップする

continue は現在の繰り返しの残りの処理をスキップして、そのまま更新式へジャンプします。ループ自体は止まらず、今回のパスだけが途中で切り上げられる、というイメージです。

index.js
Output
Click Run to see the output here.

偶数のときは continue が発動して console.log がスキップされ、奇数だけが出力されます。continue は、特定の繰り返しだけ飛ばしたいときに便利で、残りの処理を if の中にネストせずに済むのが嬉しいポイントです。

+1 以外のステップ幅にする

更新式はただの式なので、i++ である必要はありません。たとえば2ずつ増やすこともできます。

index.js
Output
Click Run to see the output here.

Count down:

index.js
Output
Click Run to see the output here.

配列を逆順でループする方法も見ておきましょう。要素を削除しながら処理したいときに便利です。

index.js
Output
Click Run to see the output here.

どんな書き方を選んでも、ルールは同じです。条件式と更新式がうまくかみ合って、最終的に条件が false になるようにしないといけません。そうならないと、ループは永遠に回り続けます。たとえば for (let i = 0; i < 10; i--) は無限ループです。i が逆方向に動いてしまっているからですね。

for文のネスト(入れ子)

for 文は中に別の for 文を入れることもできます。外側のループが1回まわるごとに、内側のループは最後まで_丸ごと_実行されます。

index.js
Output
Click Run to see the output here.

9行の出力になります。外側のループが3回、内側がそれぞれ3回ずつ回る形ですね。カウンタには同じ変数を使い回さずに、row/coli/j のように意味のわかる名前を付けましょう。

ひとつ注意したいのが、breakcontinue は一番内側のループにしか効かないという点です。内側のループを抜けても外側は止まりません。外側まで抜けたい場合は、フラグを立てて外側でチェックするか、ネストした処理を関数に切り出して return で抜ける方法を使います。

よくあるハマりどころ

初心者がつまずきやすいポイントをいくつか挙げておきます。

オフバイワンエラー。 i <= arr.length だと1つ行き過ぎ、i < arr.length - 1 だと1つ手前で止まってしまいます。定番は i < arr.length です。

更新処理の書き忘れ。 i++(あるいは相当する更新)を書き忘れると、カウンタが変わらないまま無限ループになります。

for (let i = 0; i < 10; ) {
    console.log(i); // 決して終わらない
}

カウンタに var を使う。 var は関数スコープなので、カウンタがループの外まで漏れてしまい、クロージャ絡みで思わぬ挙動を起こすことがあります。素直に let を使いましょう。

ループ中に配列を書き換える。 要素を削除するとインデックスがずれてしまい、結果として次の要素を飛ばしてしまいます。どうしても削除したいときは逆順でループするか、filter で新しい配列を作るのがおすすめです。

他の書き方を選んだほうがいい場面

昔ながらの for 文はいつでも使えますが、よくあるケースではもっと短く書ける選択肢が JavaScript にはあります。

  • 配列の値を順に取り出す: for (const item of array) のほうがすっきりします。
  • 配列を変換する: array.map(fn) で新しい配列が返ります。
  • 絞り込む: array.filter(fn)
  • 合計したり畳み込んだりする: array.reduce(fn, start)
  • 各要素に対して処理を実行するだけ: array.forEach(fn)

インデックスが本当に必要なとき、途中でスキップや break をしたいとき、逆順や 2 つ飛ばしなど変則的なステップを使いたいとき――そんなときこそ昔ながらの for 文の出番です。

次は while ループ

for 文は、回す範囲があらかじめ決まっているときに真価を発揮します。一方で、範囲が決まっていない場合――つまり「ある条件が変わるまで回し続けたい」ときには、whiledo...while のほうが向いています。次のページではそれを見ていきましょう。

よくある質問

JavaScriptのfor文の構文は?

カッコの中にセミコロンで区切った3つのパートを書きます: for (初期化; 条件; 更新) { ... }。初期化は最初の1回だけ実行され、条件は毎回のループ前にチェック、更新は各イテレーションの最後に実行されます。典型的な形は for (let i = 0; i < 10; i++) { ... } ですね。

JavaScriptで配列をループ処理するには?

インデックスを使った昔ながらのfor文なら for (let i = 0; i < arr.length; i++) { console.log(arr[i]); } でOK。インデックスが要らないなら for...of のほうがスッキリ書けます: for (const item of arr) { ... }。値の変換やフィルタリングなら、mapfilter などの配列メソッドを使うのが一般的です。

for文の中のbreakとcontinueはどう動く?

break はループを即座に抜け、そのまま直後の処理に進みます。continue は今のイテレーションの残りをスキップして更新ステップに飛び、そこから条件をもう一度チェックします。どちらもラベルを使わない限り、一番内側のループにしか効きません。

for文が無限ループになってしまうのはなぜ?

たいていは更新ステップが条件を false に近づけていないのが原因です。たとえば for (let i = 0; i < 10; i--) は、i が0から始まってどんどんマイナスになるので永遠に終わりません。条件と更新がちゃんと噛み合って、最終的に条件がfalseになるか見直してみましょう。

Coddyでコードを学ぼう

始める