【JavaScript】配列ループの新常識!for…of文の使い方とforEachとの決定的な違い

目次

概要

ES2015 (ES6) で導入された for...of 文は、配列などの反復可能なオブジェクト(イテラブル)を処理するための最もモダンで読みやすい構文です。

従来の for 文のような煩雑なインデックス管理が不要で、かつ forEach メソッドでは不可能な「ループの途中脱出(break)」や「スキップ(continue)」、さらに「非同期処理の待機(await)」が可能という強力な特徴を持っています。本記事では、ログ解析処理を例にその柔軟な挙動を解説します。

仕様(入出力)

for...of 構文

for (const element of array) {
  // 各要素に対する処理
}
構成要素説明
elementループごとに現在の要素が代入される変数。通常は const で定義します。
arrayループ対象となる配列(または文字列、Map、Setなどのイテラブル)。
  • 特徴:
    • break: ループを完全に終了します。
    • continue: 現在の周回をスキップして次へ進みます。
    • await: async 関数内で使用すれば、非同期処理を順番に実行できます。

基本の使い方

配列の値を順に取り出す

インデックス番号を気にする必要がなく、直感的に記述できます。

const scores = [80, 95, 72];

for (const score of scores) {
    console.log(`点数: ${score}`);
}
// 出力:
// 点数: 80
// 点数: 95
// 点数: 72

コード全文(HTML / JavaScript)

サーバーから取得したシステムログを解析し、表示するデモです。

「特定の重大エラー(Critical)が見つかった時点で解析を即座に中止する(break)」 という、forEach では実装できない処理を行います。

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Log Analyzer</title>
    <style>
        .log-container {
            font-family: 'Consolas', 'Monaco', monospace;
            background-color: #1e1e1e;
            color: #d4d4d4;
            padding: 20px;
            border-radius: 8px;
            width: 400px;
        }
        .log-line {
            margin: 5px 0;
            padding: 5px;
            border-left: 3px solid transparent;
        }
        .type-info { border-color: #4caf50; color: #a5d6a7; }
        .type-warning { border-color: #ff9800; color: #ffe0b2; }
        .type-critical { border-color: #f44336; color: #ffcdd2; background: #5a1010; }
        .alert-box {
            margin-top: 15px;
            padding: 10px;
            background-color: #ffeb3b;
            color: #333;
            font-weight: bold;
            display: none; /* 初期状態は非表示 */
            border-radius: 4px;
        }
    </style>
</head>
<body>

<div class="log-container">
    <h3>System Log Analysis</h3>
    <div id="log-output">
        </div>
    <div id="alert-message" class="alert-box">
        ⚠️ CRITICAL ERROR DETECTED! STOPPING...
    </div>
</div>

<script src="log_analysis.js"></script>
</body>
</html>

JavaScript

/**
 * ログ解析スクリプト
 * Criticalエラー検出時にループを脱出(break)する例
 */

// 1. 解析対象のログデータ
const serverLogs = [
    { id: 1, type: 'Info', message: 'System boot sequence started.' },
    { id: 2, type: 'Info', message: 'Network services initialized.' },
    { id: 3, type: 'Warning', message: 'High CPU usage detected (85%).' },
    { id: 4, type: 'Critical', message: 'Database connection failed!' },
    { id: 5, type: 'Info', message: 'Retry connection...' }, // これは処理されないはず
    { id: 6, type: 'Info', message: 'System shutdown.' }      // これも処理されないはず
];

// DOM要素の取得
const outputArea = document.getElementById('log-output');
const alertBox = document.getElementById('alert-message');

/**
 * ログを表示し、致命的エラーがあれば停止する関数
 */
const analyzeLogs = (logs) => {
    // for...of ループの開始
    for (const log of logs) {
        
        // ログの種類に応じたスタイルクラスを決定
        const cssClass = `type-${log.type.toLowerCase()}`;
        
        // HTML要素を作成して追加
        const logElement = document.createElement('div');
        logElement.className = `log-line ${cssClass}`;
        logElement.textContent = `[${log.type}] ${log.message}`;
        outputArea.appendChild(logElement);

        // ★ ここがポイント
        // "Critical" エラーだった場合、アラートを表示してループを強制終了する
        if (log.type === 'Critical') {
            console.warn('致命的なエラーを検知しました。解析を中断します。');
            alertBox.style.display = 'block';
            
            // break文を実行すると、このループから即座に脱出する
            // 以降のログ(id:5, id:6)は処理されない
            break;
        }
    }
};

// 実行
analyzeLogs(serverLogs);

カスタムポイント

  • continueの活用:「Warning」だけは無視してログに出さない、といった場合は if (log.type === 'Warning') { continue; } と記述すれば、その周回だけスキップして次のログ処理へ進めます。
  • 変数のスコープ:ループ変数を const ではなく let で宣言すると、ループ内でその変数に再代入することが可能になります(通常は推奨されませんが、特殊な計算ロジックで使う場合があります)。

注意点

  1. インデックスが直接取れないforEach((val, index) => ...) と異なり、for...of は標準では現在のインデックス(何番目か)を提供しません。インデックスが必要な場合は、下記の「応用」で紹介する entries() を使うか、従来の forEach を検討してください。
  2. オブジェクトはループできないconst obj = { a: 1, b: 2 }; に対して for (const val of obj) を実行するとエラーになります。オブジェクトのプロパティを回したい場合は for...in 文か Object.values(obj) を使用してください。

応用

インデックスも同時に取得したい場合

array.entries() メソッドを使うと、[インデックス, 要素] のペアを取得できるため、分割代入と組み合わせて使用します。

const fruits = ['Apple', 'Banana', 'Orange'];

for (const [index, fruit] of fruits.entries()) {
    console.log(`${index + 1}番目は ${fruit} です`);
}
// 出力:
// 1番目は Apple です
// 2番目は Banana です
// ...

まとめ

for...of 文は、現代のJavaScriptにおいて最も汎用的で強力なループ構文です。

  • 可読性が高い: of という英単語の通り、直感的に読める。
  • 制御が可能: break で停止、continue でスキップができる(forEachにはない機能)。
  • 非同期対応: for await...of を使えば非同期処理も扱える。

全要素を単純に処理するだけなら forEach も便利ですが、条件によって処理を制御したい場合は for...of を第一選択肢としてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次