JavaScriptでのプログラミングにおいて、繰り返し処理(ループ)は避けては通れない非常に重要な要素です。
大量のデータを処理したり、特定の条件に合致するまで処理を継続したりする際、ループ制御をいかに効率よく記述できるかが、コードの可読性やメンテナンス性を大きく左右します。
その中でも「特定の条件のときだけ、現在の処理をスキップして次の繰り返しに進む」という制御を可能にするのがcontinue文です。
本記事では、continue文の基本的な使い方から、実務で役立つ応用テクニック、そして使用時の注意点までを詳しく解説します。
JavaScriptのcontinue文とは何か
continue文は、実行中のループ(for、while、do...whileなど)において、現在の反復処理をその時点で終了し、次の反復処理(イテレーション)の先頭にジャンプするための命令です。
通常、ループ内のコードは上から下へと順番に実行されますが、ある特定の条件を満たした場合に「以降の処理を飛ばして、すぐに次のループへ移りたい」という場面が多々あります。
例えば、リストの中から特定のデータだけを除外して処理を続けたい場合などに、continue文が非常に有効に機能します。
continue文の基本的な構文
continue文の書き方は非常にシンプルです。
基本的には以下のように、条件分岐(if文)と組み合わせて使用されます。
// forループ内での基本的な使用例
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) {
// iが偶数の場合、これ以降の処理をスキップして次のiへ進む
continue;
}
// 奇数の場合のみ、この行が実行される
console.log(i + "は奇数です");
}
上記のコードでは、iが偶数のときにcontinueが実行されるため、その下のconsole.logは呼ばれません。
結果として奇数のみが出力されます。
forループにおけるcontinue文の挙動
最も一般的にcontinue文が使われるのはforループです。
forループでcontinueが実行されると、JavaScriptエンジンはまず「更新式(例: i++)」を実行し、その後に「条件式」の評価を行います。
実践的なコード例:特定の値をスキップする
以下は、0から5までの数値をループさせ、「3」という数値だけを無視して処理を続行する例です。
console.log("ループを開始します");
for (let i = 0; i <= 5; i++) {
if (i === 3) {
// iが3のときだけ、console.logを実行せずに次のi=4へ飛ぶ
console.log("3を見つけたのでスキップします");
continue;
}
console.log("現在の数値は: " + i);
}
console.log("ループが終了しました");
ループを開始します
現在の数値は: 0
現在の数値は: 1
現在の数値は: 2
3を見つけたのでスキップします
現在の数値は: 4
現在の数値は: 5
ループが終了しました
このように、ループ自体を完全に止める(break)のではなく、「その回だけ」をなかったことにするのがcontinueの特徴です。
break文とcontinue文の決定的な違い
初心者の方が混同しやすいのがbreak文とcontinue文の違いです。
これらはどちらもループの制御フローを変更するものですが、その影響範囲は大きく異なります。
| 命令 | 挙動の概要 | ループ自体の継続 |
|---|---|---|
| continue | 現在のステップだけを中断し、次のステップへ進む | 継続する |
| break | ループ全体の処理をその場で強制終了し、ループの外へ抜ける | 終了する |
例えば、100個のデータから「最初の1つ」を見つけたい場合はbreakが適していますが、「不適切なデータを除外して、残りすべてのデータを処理したい」という場合にはcontinueが適しています。
while文およびdo…while文での注意点
while文やdo...while文でもcontinue文を使用できますが、実装時に注意しないと無限ループに陥る危険性があります。
for文の場合、ループの最後に記述された更新式(i++など)がcontinueの後に自動的に呼び出されます。
しかし、while文ではカウンタ変数の更新をループ内の任意の位置で行うため、continueによって更新処理自体がスキップされる可能性があります。
無限ループのリスクを伴う誤った例
let i = 0;
while (i < 5) {
if (i === 2) {
// ここでiを増やさずにcontinueすると、iは2のまま固定される
// 次のループもi === 2となり、永遠にここを繰り返す
continue;
}
console.log(i);
i++;
}
このコードを実行すると、iが2になった瞬間にcontinueが呼ばれ、その下にあるi++が実行されなくなります。
その結果、iの値はずっと2のままになり、条件式i < 5を常に満たし続けて無限ループが発生します。
これを防ぐためには、continueの前に必ず更新処理を記述するか、forループの使用を検討してください。
ラベル付きcontinue文による多重ループの制御
JavaScriptには、「ラベル」と呼ばれる機能があります。
これは、特定のループに名前を付けることで、ネスト(入れ子)構造になった複雑なループの内側から、外側のループの挙動を直接コントロールするためのものです。
通常のcontinueは、自分自身が直接属している「最も内側のループ」に対してのみ作用しますが、ラベルを使用することで「親ループの次のステップへ飛ぶ」といった高度な制御が可能になります。
ラベル付きcontinueの使用例
以下の例では、2次元配列(行列)のようなネストされたデータを処理する際、特定の条件で親ループ(外側)を次の行へスキップさせています。
// 外側のループに「outerLoop」という名前(ラベル)を付ける
outerLoop: for (let i = 1; i <= 3; i++) {
console.log("--- 外側のループ: " + i + "周目 ---");
for (let j = 1; j <= 3; j++) {
if (i === 2 && j === 2) {
console.log("i=2, j=2 なので、外側のループの次のステップへ進みます");
// outerLoopというラベルがついたループの次のイテレーションへジャンプ
continue outerLoop;
}
console.log("内側のループ: " + j);
}
}
--- 外側のループ: 1周目 ---
内側のループ: 1
内側のループ: 2
内側のループ: 3
--- 外側のループ: 2周目 ---
内側のループ: 1
i=2, j=2 なので、外側のループの次のステップへ進みます
--- 外側のループ: 3周目 ---
内側のループ: 1
内側のループ: 2
内側のループ: 3
この結果からわかる通り、i=2, j=2のタイミングでcontinue outerLoopが実行されたため、その瞬間にj=3の処理はスキップされ、親ループであるi=3へと処理が移っています。
ラベル機能は多用すると構造が複雑になりがちですが、深いネストを扱う際には非常に強力な武器になります。
効率的な制御手法としての「ガード句」的な使い方
プログラミングの現場では、continue文を「ガード句」として活用することが推奨される場面があります。
ガード句とは、処理の本流に入る前に、除外すべき条件をチェックして早期に弾く手法のことです。
これにより、コードのインデント(ネスト)を浅く保ち、読みやすさを向上させることができます。
比較:if文で囲む場合 vs continueを使う場合
例えば、「数値配列の中から、正の偶数だけを抽出し、さらに100以上のものは無視して、複雑な計算を行う」という処理を考えてみましょう。
1. if文を重ねる(ネストが深くなる)例
const numbers = [10, -5, 20, 150, 30, 7];
for (const num of numbers) {
if (num > 0) {
if (num % 2 === 0) {
if (num < 100) {
// メインの処理
console.log("有効な数値です: " + num);
// ここに長いロジックが続く...
}
}
}
}
2. continueでガード句を作る(ネストが浅い)例
const numbers = [10, -5, 20, 150, 30, 7];
for (const num of numbers) {
// 条件に合わないものを次々と弾いていく
if (num <= 0) continue;
if (num % 2 !== 0) continue;
if (num >= 100) continue;
// ここまで来たら「正しいデータ」であることが確定している
console.log("有効な数値です: " + num);
// メインの処理をインデントなしで記述できる
}
比較すると一目瞭然ですが、後者の方が「どのような条件で処理をスキップしているのか」が明確であり、メインの処理がどこに記述されているのかを見つけやすくなります。
実務のコードでは「ネストを浅く保つこと」はメンテナンス性を高めるための鉄則です。
配列メソッド(forEachなど)におけるcontinueの代用
現代のJavaScript開発では、forループの代わりにArray.prototype.forEach()やmap()、filter()といった配列メソッドがよく使われます。
しかし、forEachメソッド内ではcontinue文を使用することができません。
もしforEachの中で同様のスキップ処理を行いたい場合は、return文を使用します。
const items = [1, 2, 3, 4, 5];
items.forEach((item) => {
if (item === 3) {
// continueの代わりにreturnを使う
// コールバック関数が終了し、次の要素へ移る
return;
}
console.log(item);
});
1
2
4
5
forEachにおけるreturnは、関数全体の終了ではなく「その回のコールバック関数の終了」を意味するため、実質的にcontinueと同じ役割を果たします。
ただし、breakに相当する挙動をforEachで行うことはできません。
途中で完全にループを止めたい可能性がある場合は、従来通りのfor...ofループなどを使用するのが適切です。
continue文を使いこなすためのベストプラクティス
continue文は便利ですが、使い所を間違えると逆にコードを難読化させてしまう恐れもあります。
以下のポイントを意識して使用しましょう。
- ロジックを反転させて考える
「この条件のときに実行する」と考えるのではなく、「この条件のときは何もしない」と考え、continueで先に処理を終わらせることで、メインロジックをスッキリさせることができます。 - 複雑な条件は関数化する
if文の条件式が非常に長くなる場合は、その判定自体を別の関数(述語関数)として切り出すと、if (isInvalid(data)) continue;のように、より直感的に内容を理解できるようになります。 - while文では細心の注意を払う
先述の通り、インクリメント(カウンタの更新)を忘れると深刻なバグに繋がります。while文でcontinueを使わなければならないケースでは、変数の更新フローを徹底的に検証してください。
まとめ
JavaScriptのcontinue文は、ループ処理において特定の条件をスキップし、スムーズに次の処理へと橋渡しをするための重要な制御構文です。
break文との使い分けを明確に理解し、ガード句として適切に導入することで、複雑な条件分岐が絡み合うループ処理も驚くほどシンプルに書き換えることができます。
特に大量のデータを扱うアプリケーションや、複雑なビジネスロジックを実装する際には、「いかにして不要な処理を効率よくスキップするか」という視点が欠かせません。
今回紹介したラベル付きcontinueや、ガード句としての活用パターン、そしてwhile文での注意点などを踏まえ、よりクリーンで堅牢なJavaScriptコードの記述に役立ててください。
モダンな開発においては、配列メソッドと従来のループを使い分ける判断力も求められますが、continueの仕組みを深く知ることは、プログラミングの基礎体力を向上させることに直結します。
ぜひ日々のコーディングで意識的に取り入れてみてください。
