はじめに
プログラムの制御に関わる要素として、「ループ処理」という重要な概念があります。ループ処理はデータの反復処理を実装するために使用され、同じコードを何度も記述する手間を省き、より効率的で保守性の高いコードを構築するためのものです。
この記事では、JavaScriptにおけるループ処理の基本について解説し、for文やwhile文の基本構文に触れ、条件分岐と組み合わせた基本的なループ処理の実装方法について解説します。
この記事の対象者
- JavaScript初学者の方
- 効率の良い開発を意識したい初学者の方
- ループ処理について学びたい方
- for文やwhile文の選択に迷う方
この記事で学べること
- ループ処理の基本概念
- for文とwhile文の選び方
- ループ処理と条件分岐を組み合わせた具体的な活用方法
ループ処理とは
プログラミングにおいて、同じ処理を繰り返し行うことはとても一般的です。この繰り返し処理を実現するためには、forやwhileといったキーワードを使用します。ループ処理は、一定の条件を満たす限り同じブロックのコードを繰り返し実行する仕組みになっています。これにより冗長なコードを減らし、効率的かつ簡潔なコードを記述することができます。
ループ処理はさまざまなケースで使用することができます。例えば、データの集計や配列などへのアクセス、特定の条件を満たすまでの待機など、様々なタスクを効率よく処理するために欠かせない機能です。
JavaScriptでは、ループ処理を実装する方法として様々な方法がありますが、基本は「for文」と「while文」です。これらは他のプログラミング言語でも一般的なものです(構文は異なります)。これらの基本的な概念を理解することで、JavaScriptでのループ処理を実装することができます。
for文でのループ処理
JavaScriptにおけるループ文は、基本的にはほとんどのケースでfor文が使用されます。for文について簡単に理解するために、「ループ回数があらかじめ決まっている」というケースを考えてみます。その場合、for文では「ループカウンタ変数」、ループを抜ける「条件式」、ループカウンタ変数の「更新処理」を構成要素として持ちます。
- ループカウンタ変数:ループに使用する変数です。
- 条件式:ループが実行される条件です。条件がtrueである限り、ループ処理が続きます。
- 更新処理:ループ処理が行われる度に実行されます。
for文の基本構文は以下です。
for (ループカウンタの宣言; 条件式; 更新処理) {
// ループ処理を記述
}
例として、数値の1から5をコンソールに出力してみます。
for (let i = 1; i <= 5; i++) {
console.log(i);
}
この例では、「 let i = 1; 」でループカウンタ変数を宣言し、ループを抜けるための条件として「 i <= 5; 」を定義しています。「 i 」はループカウンタとして使用する慣習的な変数名です。「 i++ 」によってループが行われる度にi変数の値が更新され、i変数の値が「 6 」になった時に「 i <= 5; 」の条件がfalseとなってループを抜けています。
更新処理については少し奇妙な記述に見えるかもしれません。
i++
これは「インクリメント」という記法で、i変数に対して「1を足す」という処理をしており、以下と同じ意味を持ちます。
i = i + 1;
i += 1; // これも同じ
逆に、「デクリメント」という記法もあります。デクリメントは変数に対して「1を引く」という処理を行います。
i--; // デクリメント
i = i - 1; // デクリメントはこれと同じ
i -= 1; // これも同じ
ループの回数を指定する場合、変数の更新処理は一般的にインクリメントやデクリメントが使用されます。
for文のポイントは、「更新処理は{}ブロックの処理が終わった後に行われる」というところです。以下はfor文の実行順を示しています。

意図したとおりにループ処理を行うには、この実行順の理解がとても重要です。例えば、更新処理に記述した処理がループを何度繰り返してもfalseにならない場合、「無限ループ」という事象が発生し、ブラウザがクラッシュする可能性があります。以下は簡単な無限ループの例です。実行しないことをオススメします。
for (let i = 1; i === 1; i++) {
i = 0;
}
for文はまず最初にループカウンタ変数の宣言を実行します。その後に条件判定を行い、条件がtrueである限りループ処理を繰り返します。
上記の例では、ループカウンタ変数の宣言「 let i = 1; 」により、条件「 i === 1; 」が成立することが分かり、条件が成立することで{}ブロック内の処理が実行されます。{}ブロック内ではループカウンタである i 変数に「 0 」を代入しており、この処理の後に「 i++ 」が実行されます。これにより、常に「 i === 1; 」が成立し、無限ループが発生します。
ループ処理を実装する場合は、このように「どのタイミングでループを抜けるための処理が実行されるか」を理解することが重要です。ループ処理を抜けるための条件を正しく指定する必要があり、誤った指定をすると無限ループや予期せぬ挙動をとる可能性があります。
while文でのループ処理
while文でのループ処理も基本的にはfor文と大差ありません。for文と同じ処理を実装すると考えると、while文ではループカウンタ変数をwhile文の外に記述し、更新処理は{}ブロック内に記述します。以下がwhile文の基本構文です。
// ループカウンタ変数を宣言
while (条件式) {
// ループ処理を記述
// 更新処理を記述
}
for文のときと同じように、while文で数値の1から5をコンソールに出力してみます。
let i = 1;
while (i <= 5) {
console.log(i);
i++;
}
while文は{}ブロック内に条件をfalseにするための処理を記述をする必要があります。while文はシンプルで直感的なので、もしかしたらfor文よりも理解しやすいと感じる方もいるかもしれません。
while文もfor文と同様、条件式がtrueである限り{}内の処理を繰り返し実行します。以下がwhile文の処理の流れです。

while文の注意点として、あらかじめループ回数が決まっている場合、変数名の衝突の可能性があるためwhile文の使用は向きません。これは、ループカウンタ変数の名前に「 i 」が使用されることが慣習であることからも理解することができるかと思います。
具体的にfor文とどのような違いがあるかを説明します。for文の場合、ループカウンタ変数は{}ブロック内の変数としてスコープを持つことになります。したがって、複数のfor文で同じ名前のループカウンタ変数を使用することができます。
for (let i = 1; i <= 5; i++) {
console.log(i);
}
/* 結果:
* 1
* 2
* 3
* 4
* 5
*/
for (let i = 10; i >= 5; i--) {
console.log(i);
}
/* 結果:
* 10
* 9
* 8
* 7
* 6
* 5
*/
while文で特定の回数のループ処理を実装する場合、ループカウンタ変数はwhile文のブロックスコープを持ちません。また、letで宣言された変数は同じスコープ内で変数名が重複することを許容しません。つまり、基本的には上記のfor文のようにループカウンタ変数を使用するときは同じ変数を利用することになります。
let i = 0;
while (i <= 5) {
console.log(i);
i++;
}
i = 10;
while (i >= 5) {
console.log(i);
i--;
}
同じ変数を違う目的で使いまわすと予期せぬ結果を生む可能性があります。{}で囲えば一応問題ありませんが、入れ子が深くなるのでfor文の方が可読性が高いです。
// while文の場合
{
let i = 0;
while (i <= 5) {
console.log(i);
i++;
}
}
{
let i = 10;
while (i >= 5) {
console.log(i);
i--;
}
}
// for文の場合
for (let i = 1; i <= 5; i++) {
console.log(i);
}
for (let i = 10; i >= 5; i--) {
console.log(i);
}
for文とwhile文は基本的に同じようなループ処理を実装することができますが、このようにどちらかが適しているというケースがあります。while文の使用は、特定のイベントやユーザーからの入力を待ち受ける場合など、繰り返す回数がわからない場合に使ってみると良いと思います。
ループ処理と条件分岐の組み合わせ
for文やwhile文によるループ処理は、条件分岐と組み合わせることで条件式がfalseにならなくてもループを抜けたり、特定の条件の場合は処理を行わずに次のループに進む(スキップする)といった制御を行うことができます。
ここではループ処理の理解を深めるために、ループ処理と条件分岐を組み合わせて少し複雑な処理を実装してみます。
break:ループを抜ける
breakを使用することで、強制的にループを抜けることができます。以下のようなループ処理を実装してみます。
- ループカウンタの値をコンソールに出力
- ループカウンタが10になるまで処理を繰り返す
- ループカウンタが8になったら強制的にループを抜ける
サンプルコードは以下です。
for (let i = 1; i <= 10; i++) {
console.log(i);
if (i === 8) {
console.log(i + 'になったのでループを終了します。');
break;
}
}
結果は以下です。
1
2
3
4
5
6
7
8
8になったのでループを終了します。
i変数の値が8の時はfor文の条件式「 i <= 10; 」が成立しているため、通常であればまだループは続くはずです。しかし、「 if (i === 8) 」で条件分岐を行い、このif文内に「 break; 」を記述しているため強制的にループを抜けています。
if (i === 8) {
console.log(i + 'になったのでループを終了します。');
break;
}
continue:ループをスキップ
continueを使用することで、特定の条件が満たされた場合にループ内の残りのコードをスキップできます。例として、1から10までの数を出力する際に、奇数の場合だけ出力をスキップしてみます。
for (let i = 1; i <= 10; i++) {
if (i % 2 === 1) {
continue;
}
console.log(i);
}
if文の条件式を「 i % 2 === 1 」としています。%演算子は除算の余りを求めるため、i 変数が奇数であれば「2」で割った値は「1」となり条件が成立します。条件が成立したら「 continue; 」が実行され、それ以降に記述してある「 console.log(i); 」は実行されずに次のループに進みます。結果は以下です。
2
4
6
8
10
breakやcontinueを使用することで、より柔軟なループ処理を実装することができます。
FizzBuzz問題を解いてみよう
プログラミングの基本を理解しているかどうかのテストとして、「FizzBuzz問題」という有名なものがあります。FizzBuzz問題はシンプルな問題ですが、基本的な制御構造や算術演算子、論理演算子を理解していないと解くことが難しいので、プログラミング初学者の方にとって良いトレーニングになります。FizzBuzz問題は以下の出力を行うというものです。
- 1から順番に数値を出力
- 3で割り切れる場合、数値のかわりに「Fizz」と出力
- 5で割り切れる場合、数値のかわりに「Buzz」と出力
- 3でも5でも割り切れる場合、数値の代わりに「FizzBuzz」と出力
具体的には、以下のような出力を行います。ここでは15までの数値を出力しています。
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
FizzBuzz問題の解答例もご用意しましたが、初学者の方はまずご自身の力でFizzBuzz問題にチャレンジしてみると良いと思います。
for (let i = 1; i <= 100; i++) {
if (i % 3 === 0 && i % 5 === 0) {
console.log("FizzBuzz");
} else if (i % 3 === 0) {
console.log("Fizz");
} else if (i % 5 === 0) {
console.log("Buzz");
} else {
console.log(i);
}
}
最後に
この記事では、JavaScriptにおいてのループ処理について焦点を当て、for文とwhile文の基本構文や、これらをどのように選択するかについて解説しました。for文とwhile文の選択は人の好みにもよりますが、一般的にはfor文が広く使われています。
また、ループ処理内で条件分岐を行うことにより、breakやcontinueを利用した柔軟なループ処理の実装方法について学びました。この記事の内容は、プログラミングの基本知識としてJavaScriptだけでなく多くの言語でも参考になるかと思います。
ループ処理と密接に関わるもので「配列」というものがあります。配列を用いることで、複数のデータをまとめて処理することができるようになり、ループ処理をより効果的に実装することができます。以下の記事では配列についてJavaScript初学者の方向けに解説しています。ループ処理について学んだ方に向けた内容なので、参考にしていただけると幸いです。
