JavaScript にはループ処理の書き方が複数あり、場面に応じて使い分ける必要があります。for 文、for...of、forEach、while、そして map / filter / reduce などの配列メソッド。それぞれの特徴と使い分けの判断基準を解説します。
・for 文の基本構文
・for…of で配列・文字列・Map・Set をループ
・for…in でオブジェクトのキーを列挙
・forEach / map / filter / reduce の違い
・while / do…while の使いどころ
・break / continue でループを制御する方法
・各ループの使い分け早見表
for 文(基本のカウントループ)
// 0 から 4 まで(5 回)ループ
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}
// 配列のインデックスでループ
const fruits = ["apple", "banana", "cherry"];
for (let i = 0; i < fruits.length; i++) {
console.log(`${i}: ${fruits[i]}`);
}
// 逆順ループ
for (let i = fruits.length - 1; i >= 0; i--) {
console.log(fruits[i]); // cherry, banana, apple
}
・インデックス番号が必要な場合
・逆順やステップ(2 ずつ等)のループ
・break / continue で途中制御したい場合
配列の単純な全要素ループには
for...of や forEach の方がシンプルです。for…of(配列・文字列・Map・Set のループ)
// 配列
const colors = ["red", "green", "blue"];
for (const color of colors) {
console.log(color); // red, green, blue
}
// 文字列(1 文字ずつ)
for (const char of "Hello") {
console.log(char); // H, e, l, l, o
}
// Map
const map = new Map([["a", 1], ["b", 2]]);
for (const [key, value] of map) {
console.log(`${key}: ${value}`); // a: 1, b: 2
}
// Set
const set = new Set([1, 2, 3]);
for (const num of set) {
console.log(num); // 1, 2, 3
}
// NodeList(DOM 要素)
for (const el of document.querySelectorAll(".item")) {
el.classList.add("active");
}
インデックスが不要で要素だけ処理する場合、
for...of が最もシンプルです。break / continue も使えるため、forEach より制御が柔軟です。for…in(オブジェクトのキー列挙)
// オブジェクトのキーを列挙
const user = { name: "Tanaka", age: 30, role: "admin" };
for (const key in user) {
console.log(`${key}: ${user[key]}`);
// name: Tanaka, age: 30, role: admin
}
for...in は「列挙可能なプロパティのキー」を返すため、配列に使うとインデックスが文字列で返り、プロトタイプチェーンのプロパティも列挙される可能性があります。配列には for...of を使ってください。for...in はオブジェクトのキー列挙専用です。| 構文 | 反復対象 | 返す値 | 配列に使う |
|---|---|---|---|
| for…of | 配列 / 文字列 / Map / Set / NodeList | 値(要素そのもの) | 推奨 |
| for…in | オブジェクト | キー(プロパティ名) | 非推奨 |
forEach(配列メソッド)
const fruits = ["apple", "banana", "cherry"];
// 要素だけ
fruits.forEach(fruit => {
console.log(fruit);
});
// 要素 + インデックス
fruits.forEach((fruit, index) => {
console.log(`${index}: ${fruit}`);
});
// 第 3 引数で元の配列にアクセス
fruits.forEach((fruit, index, arr) => {
console.log(`${fruit} (全${arr.length}件中)`);
});
forEach 内で break を書くと SyntaxError になります。途中でループを抜けたい場合は for...of を使うか、some() / every() で代替してください。return は continue 相当(その回だけスキップ)として動作します。map / filter / reduce(変換・絞り込み・集計)
// 各要素を変換して新しい配列を返す
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// オブジェクト配列から特定のプロパティだけ抽出
const users = [{ name: "A", age: 20 }, { name: "B", age: 30 }];
const names = users.map(u => u.name);
console.log(names); // ["A", "B"]
// 条件に合う要素だけの新しい配列を返す const numbers = [1, 2, 3, 4, 5]; const evens = numbers.filter(n => n % 2 === 0); console.log(evens); // [2, 4] // 空文字を除外 const items = ["apple", "", "banana", "", "cherry"]; const nonEmpty = items.filter(Boolean); console.log(nonEmpty); // ["apple", "banana", "cherry"]
// 合計を計算
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum); // 15
// オブジェクトに集約
const fruits = ["apple", "banana", "apple", "cherry", "banana", "apple"];
const count = fruits.reduce((acc, fruit) => {
acc[fruit] = (acc[fruit] || 0) + 1;
return acc;
}, {});
console.log(count); // { apple: 3, banana: 2, cherry: 1 }
| メソッド | 動作 | 戻り値 | 用途 |
|---|---|---|---|
| forEach | 各要素に処理を実行 | undefined(戻り値なし) | 副作用のある処理(DOM 操作等) |
| map | 各要素を変換 | 新しい配列(同じ長さ) | 配列の変換(値の加工・抽出) |
| filter | 条件で絞り込み | 新しい配列(条件に合う要素だけ) | 条件に合う要素の抽出 |
| reduce | 1 つの値に集約 | 任意の値(合計・オブジェクト等) | 合計・カウント・グルーピング |
forEach は戻り値がなく(undefined)、副作用のある処理に使います。map は変換後の新しい配列を返すため、配列の変換に使います。「結果を使うなら map、使わないなら forEach」と覚えてください。while / do…while
// while: 条件が true の間ループ
let i = 0;
while (i < 5) {
console.log(i); // 0, 1, 2, 3, 4
i++;
}
// do...while: 最低 1 回は実行
let j = 10;
do {
console.log(j); // 10(条件は false だが 1 回は実行)
j++;
} while (j < 5);
// 実用例: ランダムな値が条件を満たすまでループ
let random;
do {
random = Math.random();
} while (random < 0.9);
console.log(`0.9 以上の値: ${random}`);
条件が永遠に true のままだとブラウザがフリーズします。
while (true) を使う場合は内部に break を必ず書いてください。break / continue でループを制御する
// break: ループを途中で終了
for (let i = 0; i < 10; i++) {
if (i === 5) break; // 5 でループ終了
console.log(i); // 0, 1, 2, 3, 4
}
// continue: その回だけスキップして次へ
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) continue; // 偶数をスキップ
console.log(i); // 1, 3, 5, 7, 9
}
// for...of + break: 配列から条件に合う最初の要素を見つける
const items = [1, 3, 5, 8, 10];
let firstEven;
for (const item of items) {
if (item % 2 === 0) {
firstEven = item;
break;
}
}
console.log(firstEven); // 8
// ↑ Array.find() で書くとより簡潔
const firstEven2 = items.find(n => n % 2 === 0); // 8
| 構文 | break | continue |
|---|---|---|
| for / for…of / for…in / while | 使える | 使える |
| forEach / map / filter / reduce | 使えない | 使えない(return でスキップ) |
オブジェクトのループ方法
const user = { name: "Tanaka", age: 30, role: "admin" };
// Object.keys: キーの配列
Object.keys(user).forEach(key => {
console.log(`${key}: ${user[key]}`);
});
// Object.values: 値の配列
Object.values(user).forEach(value => {
console.log(value); // "Tanaka", 30, "admin"
});
// Object.entries: [key, value] のペア配列
for (const [key, value] of Object.entries(user)) {
console.log(`${key}: ${value}`);
}
for...in はプロトタイプチェーンのプロパティも列挙するリスクがあります。Object.entries() + for...of なら自身のプロパティのみ安全に列挙できます。ループの使い分け早見表
| 場面 | 推奨 | 理由 |
|---|---|---|
| 配列を全要素ループ(インデックス不要) | for…of | シンプルで break も使える |
| 配列を全要素ループ(インデックス必要) | for / forEach | for はインデックス変数、forEach は第 2 引数 |
| 配列を変換して新しい配列を作る | map | 戻り値が新しい配列 |
| 配列から条件に合う要素を抽出 | filter | 条件に合う要素だけの配列 |
| 配列を 1 つの値に集約 | reduce | 合計 / カウント / グルーピング |
| 最初に条件に合う要素を見つける | find / for…of + break | find が最もシンプル |
| オブジェクトのキーと値をループ | Object.entries + for…of | 安全で分割代入も使える |
| 回数が決まっていないループ | while | 条件が true の間繰り返す |
| DOM 要素のリストをループ | for…of / forEach | NodeList を反復 |
実務パターン集
パターン(1): DOM 要素に一括でイベントを登録
document.querySelectorAll(".btn").forEach(btn => {
btn.addEventListener("click", () => {
console.log(btn.textContent);
});
});
パターン(2): API レスポンスの配列を変換
const apiUsers = [
{ id: 1, firstName: "Taro", lastName: "Yamada" },
{ id: 2, firstName: "Hanako", lastName: "Suzuki" },
];
// フルネームの配列に変換
const fullNames = apiUsers.map(u => `${u.lastName} ${u.firstName}`);
console.log(fullNames); // ["Yamada Taro", "Suzuki Hanako"]
パターン(3): チェーン(filter + map)
const products = [
{ name: "Apple", price: 150, inStock: true },
{ name: "Banana", price: 100, inStock: false },
{ name: "Cherry", price: 300, inStock: true },
];
// 在庫ありの商品名だけ抽出
const available = products
.filter(p => p.inStock)
.map(p => p.name);
console.log(available); // ["Apple", "Cherry"]
パターン(4): reduce で集計
// カテゴリ別に商品をグルーピング
const items = [
{ name: "A", category: "food" },
{ name: "B", category: "drink" },
{ name: "C", category: "food" },
];
const grouped = items.reduce((acc, item) => {
const key = item.category;
(acc[key] ??= []).push(item);
return acc;
}, {});
// { food: [{...}, {...}], drink: [{...}] }
よくある質問
forEach がシンプルです。break が必要な場合は for...of を使ってください。forEach では break が使えません。forEach では break は使えません。代替手段は (1) for...of + break、(2) Array.some()(return true で停止)、(3) Array.find()(最初の一致で停止)です。for...of は値を返し、配列・文字列・Map・Set に使います。for...in はキー(プロパティ名)を返し、オブジェクトに使います。配列には for…in を使わないでください(インデックスが文字列で返り、プロトタイプのプロパティも列挙されるため)。map は変換後の新しい配列を返すため、結果を使う場合に使います。forEach はundefined を返すため、DOM 操作やログ出力など副作用のある処理に使います。for が最速ですが、実務で体感差が出ることはほとんどありません。forEach 内の async は並列実行になり await が期待通りに動きません。for…of を使えば順次実行されます。for (const item of items) { await process(item); }まとめ
JavaScript のループ処理の要点をまとめます。
| やりたいこと | 推奨 |
|---|---|
| 配列を全要素ループ | for…of / forEach |
| 配列を変換 | map |
| 配列を絞り込み | filter |
| 配列を 1 つの値に集約 | reduce |
| 最初に条件に合う要素を見つける | find |
| インデックス付きでループ | for / forEach(第 2 引数)/ entries() |
| 途中で break したい | for / for…of(forEach は不可) |
| オブジェクトをループ | Object.entries() + for…of |
| 回数不定のループ | while / do…while |
| async/await で順次処理 | for…of(forEach は不可) |

