JavaScript | 配列・オブジェクト:ループ処理 – for…of

JavaScript JavaScript
スポンサーリンク

for…of とは何か

for…of は「配列など“反復可能(イテラブル)”なものを、要素の値にフォーカスしてシンプルに処理する」構文です。ここが重要です:for…of は“値”を1つずつ取り出します。インデックスが不要な処理に最適で、continue や break にも対応し、読みやすさと安全性のバランスが良いループです。


基本の使い方(配列の値を順に処理)

値をそのまま取り出す

const nums = [10, 20, 30];
for (const n of nums) {
  console.log(n); // 10, 20, 30
}
JavaScript

ここが重要です:for…of は配列の長さや位置を意識せず“値だけ”を扱えます。インデックス管理のミス(<= で1回余分に回るなど)が起きません。

continue/break で制御する

for (const n of [1, 0, 3, 0, 5]) {
  if (n === 0) continue; // 0 を飛ばす
  console.log(n);        // 1, 3, 5
}

for (const n of [2, 4, 6, 7, 8]) {
  if (n % 2 !== 0) break; // 奇数で停止
  console.log(n);         // 2, 4, 6
}
JavaScript

ここが重要です:for…of は早期終了・スキップが簡単。副作用だけの処理なら forEach、柔軟な制御なら for…of が向いています。


インデックスが欲しいとき(entries を使う)

値とインデックスを同時に取り出す

const arr = ["A", "B", "C"];
for (const [i, v] of arr.entries()) {
  console.log(i, v); // 0 "A", 1 "B", 2 "C"
}
JavaScript

ここが重要です:for…of は“値中心”。位置も必要なら entries() を組み合わせれば、読みやすさを保ったままインデックスにアクセスできます。


for…of と for/for…in の違い(重要な使い分け)

for…of と for の違い

  • 目的: for…of は“値中心”、for は“インデックス中心で細かい制御”。
  • 読みやすさ: 値だけ使うなら for…of が短く安全。部分処理・逆順・ページングなどインデックス制御が必要なら for。

for…of と for…in の違い

const arr = ["x", "y"];
for (const i in arr) { /* "0","1"(キー=文字列) */ }
for (const v of arr)  { /* "x","y"(値) */ }
JavaScript

ここが重要です:for…in は“オブジェクトのキー列挙”用で、配列には不向きです(順序保証が弱く、プロトタイプ拡張の影響を受けることがある)。配列は必ず for…of を使いましょう。


反復可能(イテラブル)の広がり

文字列・Set・Map にも使える

// 文字列
for (const ch of "こんにちは") console.log(ch);

// Set(重複なしの集合)
const s = new Set([1, 2, 2]);
for (const v of s) console.log(v); // 1, 2

// Map(キーと値のペア)
const m = new Map([["id", 1], ["name", "Alice"]]);
for (const [k, v] of m) console.log(k, v); // "id" 1 / "name" "Alice"
JavaScript

ここが重要です:for…of は“イテラブル一般”を扱えます。配列以外のコレクションでも、自然に値へアクセスできます。


疎配列・undefined の挙動(配列の穴に注意)

空スロットは“undefined として”反復される

const sparse = Array(3); // [ <3 empty items> ]
for (const v of sparse) console.log(v); // undefined, undefined, undefined
JavaScript

ここが重要です:for…of は“反復の視点”でスロットを辿るため、空スロットも undefined として現れます。map/filter は空スロットをスキップするので挙動が違います。欠損を除去したいなら事前に正規化やフィルタを入れましょう。

const xs = [undefined, 1, null, 2];
for (const v of xs.filter(x => x != null)) console.log(v); // 1, 2
JavaScript

非同期処理との組み合わせ(await を使う)

逐次的に await しながら処理(順序保証)

async function fetchAll(ids) {
  const results = [];
  for (const id of ids) {
    const res = await fetch(`/api/${id}`);
    results.push(await res.json());
  }
  return results;
}
JavaScript

ここが重要です:for…of は await と相性が良い(1件ずつ確実に処理)。並列で良いなら map で Promise を作り、Promise.all でまとめる方が速いこともあります。


実務レシピ(読みやすく安全に書くための定番)

変換+抽出(非破壊の基本形)

const labels = [];
for (const p of products) {
  if (p.stock > 0) labels.push(`${p.name} (${p.price})`);
}
// filter+map を 1 パスで
JavaScript

合計・検証・早期終了

let sum = 0;
for (const n of nums) {
  if (!Number.isFinite(n)) { sum = NaN; break; }
  sum += n;
}
JavaScript

ページング(範囲を for…of で回す)

const page = arr.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize);
for (const item of page) {
  // 表示処理
}
JavaScript

ここが重要です:範囲切り出しは slice、ループは for…of。役割を分けると読みやすい。


パフォーマンスと設計の指針

ループ中に配列を破壊的変更しない

配列を push/splice で変えると、意図しない重複・取りこぼしが起きます。結果は別配列へ(非破壊)に入れるのが基本です。

インデックスが本当に必要か見極める

値だけで書けるなら for…of を選ぶと、ミスが減り可読性が上がります。位置が必要なら entries()、高度な制御なら通常の for。

事前の正規化でコストを下げる

大文字小文字の統一、型変換、欠損除去などは for…of の前に済ませると、ループが簡潔になり性能も安定します。


まとめ

for…of は「イテラブルの“値”をシンプルに処理する」ループ構文です。インデックス不要の処理に強く、continue/break/await と組み合わせて柔軟に書けます。インデックスが欲しければ entries()、配列の穴は undefined として現れる挙動に注意。配列をループ中に壊さず、役割分離(範囲は slice、検証は前処理)を徹底すれば、初心者でも読みやすく安全なループを短く正確に書けます。

タイトルとURLをコピーしました