Overview
Introduced in ES2015 (ES6), the for…of statement is the most modern and readable syntax for processing iterable objects like arrays. Unlike traditional for loops, it eliminates the need for complex index management. More importantly, it provides powerful features that the forEach method lacks, such as the ability to stop a loop early with break, skip iterations with continue, and wait for asynchronous tasks with await. This article demonstrates these flexible behaviors using a system log analysis scenario.
Specifications (Input/Output)
- Input: An array of system log objects (e.g., Error, Warning, Info).
- Output: Logs rendered to the screen.
- Operation: * Iterate through the logs and stop immediately if a “Critical” error is detected.
- Use
breakto prevent further processing after a fatal error.
- Use
The for…of Syntax
for (const element of array) {
// Logic for each element
}
| Component | Description |
| element | A variable assigned the value of the current element in each iteration. Usually defined with const. |
| array | The array (or other iterable like String, Map, or Set) to be looped through. |
Key Control Features
- break: Terminates the loop completely.
- continue: Skips the current iteration and moves to the next one.
- await: When used inside an
asyncfunction, it allows you to execute asynchronous operations in sequence.
Basic Usage
Extracting values from an array is intuitive because you do not have to manage index numbers.
const hardwareIds = [1024, 2048, 4096];
for (const id of hardwareIds) {
console.log(`Device ID: ${id}`);
}
/*
Output:
Device ID: 1024
Device ID: 2048
Device ID: 4096
*/
Full Code (Log Analysis Scenario)
This demo analyzes system logs fetched from a server. It performs a task that is impossible with forEach: stopping the analysis immediately (break) as soon as a “Critical” error is found.
HTML
<!DOCTYPE html>
<html lang="en">
<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: 450px;
}
.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">
<h2>System Log Analysis</h2>
<div id="log-output">
</div>
<div id="alert-message" class="alert-box">
⚠️ CRITICAL ERROR DETECTED! ANALYSIS ABORTED.
</div>
</div>
<script src="log_analysis.js"></script>
</body>
</html>
JavaScript
/**
* Log Analysis Script
* Example of breaking out of a loop when a Critical error is detected.
*/
// 1. Log data to be analyzed
const systemLogs = [
{ id: 1, type: 'Info', message: 'Mainframe communication established.' },
{ id: 2, type: 'Info', message: 'Security protocols active.' },
{ id: 3, type: 'Warning', message: 'Unusual traffic on port 80.' },
{ id: 4, type: 'Critical', message: 'Kernel panic detected in node-02!' },
{ id: 5, type: 'Info', message: 'Attempting automated recovery...' }, // This will not be processed
{ id: 6, type: 'Info', message: 'Cleanup task started.' } // This will not be processed
];
const outputArea = document.getElementById('log-output');
const alertBox = document.getElementById('alert-message');
/**
* Function to display logs and stop if a fatal error occurs
*/
const runLogAnalysis = (logs) => {
// Start of the for...of loop
for (const log of logs) {
// Determine the CSS class based on log type
const cssClass = `type-${log.type.toLowerCase()}`;
// Create and append the log element
const logElement = document.createElement('div');
logElement.className = `log-line ${cssClass}`;
logElement.textContent = `[${log.type}] ${log.message}`;
outputArea.appendChild(logElement);
// Key Logic:
// If a "Critical" error is detected, show an alert and stop the loop.
if (log.type === 'Critical') {
console.warn('Fatal error detected. Aborting analysis.');
alertBox.style.display = 'block';
// The break statement exits the loop immediately.
// Logs with id:5 and id:6 will be ignored.
break;
}
}
};
// Execute the analysis
runLogAnalysis(systemLogs);
Customization Points
- Using continue: If you want to ignore certain log types (e.g., skip “Warning” logs without stopping the loop), use
if (log.type === 'Warning') { continue; }. This skips the current turn and moves to the next log. - Variable Scope: While
constis standard for the loop variable, you can useletif you need to reassign the variable within the loop block for specific calculation logic.
Important Notes
- Indices are not provided: Unlike
forEach((val, index) => ...),for...ofdoes not naturally provide the current index. If you need the position, you must use theentries()method as shown in the advanced section. - Objects are not iterable: Running
for (const val of obj)on a plain object like{a: 1}will throw an error. To iterate through object properties, usefor...inorObject.values(obj).
Advanced Applications
If you need to access both the value and the index, use the entries() method along with destructuring.
const services = ['Auth', 'Database', 'Cache'];
for (const [index, service] of services.entries()) {
console.log(`Service #${index + 1}: ${service}`);
}
/*
Output:
Service #1: Auth
Service #2: Database
Service #3: Cache
*/
Summary
The for…of loop is the most versatile and powerful iteration syntax in modern JavaScript because it combines high readability with granular control. It allows developers to intuitively loop through arrays without managing indices while providing the essential capability to stop or skip iterations using break and continue. While forEach remains useful for simple operations on every element, for…of should be your first choice whenever you need to control the flow of the loop or handle asynchronous logic. Understanding these structural differences ensures that your data processing remains efficient and your code remains easy to maintain.
