Welcome back! 👋 In the previous lesson, you mastered the do...while loop. Now let's explore one of the most elegant loops in modern JavaScript — the for...of loop!
The for...of loop was introduced in ES6 and immediately became the go-to for iterating over arrays, strings, and other iterables. No index tracking, no array[i], no off-by-one errors — just clean, direct access to each value, one by one.
Let's break it down completely!
What is a for...of Loop?
A for...of loop iterates over the values of any iterable — arrays, strings, Sets, Maps, and more. Each iteration gives you the next value directly, without needing to manage an index.
let fruits = ["Apple", "Banana", "Mango"];
for (let fruit of fruits) {
console.log(fruit);
}
// Output:
// Apple
// Banana
// MangoCompare this to the traditional for loop doing the same thing:
// Traditional for — you manage the index manually
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
// for...of — no index, just the value ✅
for (let fruit of fruits) {
console.log(fruit);
}Same result. The for...of version is shorter, cleaner, and far less error-prone.
Syntax
for (let value of iterable) {
// use value
}value— a new variable that holds the current item on each iterationof— the keyword that separates the variable from the iterableiterable— any object that is iterable: array, string, Set, Map, etc.
What is an Iterable?
An iterable is any object that can be looped over with for...of. JavaScript has several built-in iterables:
| Iterable | What you get |
|---|---|
Array | Each element value |
String | Each character |
Set | Each unique value |
Map | Each [key, value] pair |
NodeList | Each DOM element |
Plain objects {} are not iterable — use for...in for those (covered in the next lesson).
Iterating Over Arrays
The most common use of for...of — clean, simple array iteration.
Basic Array
let colors = ["Red", "Green", "Blue", "Yellow"];
for (let color of colors) {
console.log(color);
}
// Output:
// Red
// Green
// Blue
// YellowArray of Numbers
let scores = [88, 92, 75, 60, 95];
let total = 0;
for (let score of scores) {
total += score;
}
console.log(`Total: ${total}`);
console.log(`Average: ${total / scores.length}`);
// Output:
// Total: 410
// Average: 82Array of Objects
let students = [
{ name: "Mihir", marks: 92 },
{ name: "Priya", marks: 85 },
{ name: "Rahul", marks: 78 },
{ name: "Sara", marks: 95 },
];
for (let student of students) {
let grade = student.marks >= 90 ? "A" : student.marks >= 80 ? "B" : "C";
console.log(`${student.name}: ${student.marks} marks — Grade ${grade}`);
}
// Output:
// Mihir: 92 marks — Grade A
// Priya: 85 marks — Grade B
// Rahul: 78 marks — Grade C
// Sara: 95 marks — Grade AIterating Over Strings
for...of treats a string as a sequence of characters — each iteration gives you one character.
let word = "JavaScript";
for (let char of word) {
process.stdout.write(char + " ");
}
// Output: J a v a S c r i p t// Count vowels in a string
let sentence = "Hello World";
let vowelCount = 0;
let vowels = "aeiouAEIOU";
for (let char of sentence) {
if (vowels.includes(char)) {
vowelCount++;
}
}
console.log(`Vowels in "${sentence}": ${vowelCount}`);
// Output: Vowels in "Hello World": 3// Reverse a string
let original = "Mihir";
let reversed = "";
for (let char of original) {
reversed = char + reversed;
}
console.log(`Reversed: ${reversed}`);
// Output: Reversed: rihiMGetting the Index with entries()
for...of doesn't give you the index by default — but you can get both the index and value using array.entries().
let items = ["Laptop", "Phone", "Tablet", "Watch"];
for (let [index, item] of items.entries()) {
console.log(`${index + 1}. ${item}`);
}
// Output:
// 1. Laptop
// 2. Phone
// 3. Tablet
// 4. Watch// Find index of matching item
let products = ["Apple", "Samsung", "OnePlus", "Xiaomi"];
for (let [i, product] of products.entries()) {
if (product === "OnePlus") {
console.log(`Found "OnePlus" at index ${i} ✅`);
break;
}
}
// Output: Found "OnePlus" at index 2 ✅Iterating Over a Set
A Set stores unique values only. for...of iterates over each unique value.
let uniqueTags = new Set(["javascript", "html", "css", "javascript", "html"]);
for (let tag of uniqueTags) {
console.log(tag);
}
// Output:
// javascript
// html
// css
// (duplicates are automatically removed by Set)// Remove duplicates from an array using Set + for...of
let rawScores = [85, 92, 85, 78, 92, 60, 78];
let uniqueScores = new Set(rawScores);
let result = [];
for (let score of uniqueScores) {
result.push(score);
}
console.log("Unique scores:", result);
// Output: Unique scores: [85, 92, 78, 60]Iterating Over a Map
A Map stores key-value pairs. Each iteration of for...of gives you a [key, value] array.
let userRoles = new Map([
["Mihir", "Admin"],
["Priya", "Editor"],
["Rahul", "Viewer"],
["Sara", "Admin"],
]);
for (let [name, role] of userRoles) {
console.log(`${name} → ${role}`);
}
// Output:
// Mihir → Admin
// Priya → Editor
// Rahul → Viewer
// Sara → Admin// Count items per category
let inventory = new Map([
["Electronics", 45],
["Clothing", 120],
["Books", 88],
["Toys", 34],
]);
let grandTotal = 0;
for (let [category, qty] of inventory) {
console.log(`${category.padEnd(15)}: ${qty} items`);
grandTotal += qty;
}
console.log(`\nTotal Items: ${grandTotal}`);
// Output:
// Electronics : 45 items
// Clothing : 120 items
// Books : 88 items
// Toys : 34 items
// Total Items: 287break — Exit the Loop Early
// Find the first student who scored above 90
let scores = [72, 68, 91, 85, 97, 60];
for (let score of scores) {
if (score > 90) {
console.log(`First score above 90: ${score} 🏆`);
break;
}
}
// Output: First score above 90: 91 🏆// Stop processing once budget is exceeded
let expenses = [500, 1200, 800, 2000, 300];
let budget = 3000;
let spent = 0;
for (let expense of expenses) {
if (spent + expense > budget) {
console.log(`❌ Over budget! Cannot add ₹${expense}. Spent so far: ₹${spent}`);
break;
}
spent += expense;
console.log(`✅ Added ₹${expense} | Total spent: ₹${spent}`);
}
// Output:
// ✅ Added ₹500 | Total spent: ₹500
// ✅ Added ₹1200 | Total spent: ₹1700
// ✅ Added ₹800 | Total spent: ₹2500
// ❌ Over budget! Cannot add ₹2000. Spent so far: ₹2500continue — Skip an Iteration
// Skip out-of-stock items
let products = [
{ name: "Laptop", inStock: true },
{ name: "Mouse", inStock: false },
{ name: "Monitor", inStock: true },
{ name: "Webcam", inStock: false },
{ name: "Keyboard",inStock: true },
];
console.log("Available Products:");
for (let product of products) {
if (!product.inStock) continue;
console.log(`✅ ${product.name}`);
}
// Output:
// Available Products:
// ✅ Laptop
// ✅ Monitor
// ✅ Keyboard// Skip negative numbers, sum only positives
let numbers = [10, -5, 30, -8, 20, -2, 15];
let sum = 0;
for (let num of numbers) {
if (num < 0) continue;
sum += num;
}
console.log(`Sum of positive numbers: ${sum}`);
// Output: Sum of positive numbers: 75Real-World Examples
Example 1: Shopping Cart Total
let cart = [
{ name: "Notebook", price: 120, qty: 3 },
{ name: "Pen", price: 20, qty: 10 },
{ name: "Eraser", price: 10, qty: 5 },
{ name: "Ruler", price: 35, qty: 2 },
];
let grandTotal = 0;
console.log("===== CART =====");
for (let item of cart) {
let subtotal = item.price * item.qty;
grandTotal += subtotal;
console.log(`${item.name.padEnd(12)} ₹${item.price} × ${item.qty} = ₹${subtotal}`);
}
console.log("================");
console.log(`TOTAL: ₹${grandTotal}`);
// Output:
// ===== CART =====
// Notebook ₹120 × 3 = ₹360
// Pen ₹20 × 10 = ₹200
// Eraser ₹10 × 5 = ₹50
// Ruler ₹35 × 2 = ₹70
// ================
// TOTAL: ₹680Example 2: Find Max and Min Score
let scores = [67, 92, 45, 88, 73, 99, 55];
let max = scores[0];
let min = scores[0];
for (let score of scores) {
if (score > max) max = score;
if (score < min) min = score;
}
console.log(`🏆 Highest: ${max}`);
console.log(`📉 Lowest: ${min}`);
// Output:
// 🏆 Highest: 99
// 📉 Lowest: 45Example 3: Word Frequency Counter
let words = ["apple", "banana", "apple", "cherry", "banana", "apple"];
let frequency = {};
for (let word of words) {
frequency[word] = (frequency[word] || 0) + 1;
}
for (let [word, count] of Object.entries(frequency)) {
console.log(`${word}: ${"⭐".repeat(count)} (${count})`);
}
// Output:
// apple: ⭐⭐⭐ (3)
// banana: ⭐⭐ (2)
// cherry: ⭐ (1)Example 4: Flatten Nested Array
let nested = [[1, 2], [3, 4], [5, 6], [7, 8]];
let flat = [];
for (let group of nested) {
for (let num of group) {
flat.push(num);
}
}
console.log("Flattened:", flat);
// Output: Flattened: [1, 2, 3, 4, 5, 6, 7, 8]Example 5: Employee Payroll Report
let employees = [
{ name: "Mihir", dept: "Engineering", salary: 85000 },
{ name: "Priya", dept: "Design", salary: 72000 },
{ name: "Rahul", dept: "Engineering", salary: 91000 },
{ name: "Sara", dept: "Marketing", salary: 68000 },
{ name: "Arjun", dept: "Engineering", salary: 78000 },
];
let totalPayroll = 0;
let deptCount = {};
console.log("=== Payroll Report ===");
for (let emp of employees) {
totalPayroll += emp.salary;
deptCount[emp.dept] = (deptCount[emp.dept] || 0) + 1;
console.log(`${emp.name.padEnd(8)} | ${emp.dept.padEnd(14)} | ₹${emp.salary.toLocaleString()}`);
}
console.log("\n=== Department Summary ===");
for (let [dept, count] of Object.entries(deptCount)) {
console.log(`${dept}: ${count} employee(s)`);
}
console.log(`\nTotal Payroll: ₹${totalPayroll.toLocaleString()}`);
// Output:
// Mihir | Engineering | ₹85,000
// Priya | Design | ₹72,000
// ...
// Engineering: 3 employee(s)
// Design: 1 employee(s)
// Marketing: 1 employee(s)
// Total Payroll: ₹3,94,000for...of vs for vs for...in
let arr = ["A", "B", "C"];
// for — index-based, need to manage i manually
for (let i = 0; i < arr.length; i++) {
console.log(i, arr[i]); // 0 A, 1 B, 2 C
}
// for...of — gives values directly, clean and simple ✅
for (let val of arr) {
console.log(val); // A, B, C
}
// for...in — gives string indexes, NOT recommended for arrays ❌
for (let key in arr) {
console.log(key); // "0", "1", "2" ← string keys, not values!
}| Loop | Gives you | Works on | Use when |
|---|---|---|---|
for | Index + value (manually) | Arrays | You need index control |
for...of | Values directly | Arrays, Strings, Sets, Maps | You just need values |
for...in | Keys/property names | Objects | You need object keys |
Common Mistakes
Mistake 1: Using for...of on a Plain Object
let person = { name: "Mihir", age: 25 };
// ❌ TypeError — plain objects are NOT iterable!
for (let val of person) {
console.log(val);
}
// ✅ Use Object.values() to iterate over values
for (let val of Object.values(person)) {
console.log(val); // "Mihir", 25
}
// ✅ Use Object.entries() to get key-value pairs
for (let [key, val] of Object.entries(person)) {
console.log(`${key}: ${val}`); // name: Mihir, age: 25
}
// ✅ Use for...in for object keys (next lesson!)
for (let key in person) {
console.log(key); // name, age
}Mistake 2: Expecting an Index Without entries()
let colors = ["Red", "Green", "Blue"];
// ❌ `color` is the value, not the index — index is not available directly
for (let color of colors) {
console.log(color, i); // ❌ ReferenceError: i is not defined
}
// ✅ Use entries() when you need both
for (let [index, color] of colors.entries()) {
console.log(index, color); // 0 Red, 1 Green, 2 Blue ✅
}Mistake 3: Modifying the Array While Iterating
let nums = [1, 2, 3, 4, 5];
// ❌ Pushing inside for...of can cause unexpected behavior
for (let num of nums) {
if (num === 3) nums.push(6); // Modifying while iterating — unpredictable!
console.log(num);
}
// ✅ Work on a copy, or collect changes and apply after
let toAdd = [];
for (let num of nums) {
if (num === 3) toAdd.push(6);
console.log(num);
}
nums.push(...toAdd); // Apply after loop ✅Mistake 4: Using for...of When You Need the Index for Updates
let prices = [100, 200, 300];
// ❌ Can't directly update array values via for...of
for (let price of prices) {
price = price * 1.1; // This only changes the local variable, NOT the array!
}
console.log(prices); // [100, 200, 300] — unchanged ❌
// ✅ Use classic for loop when you need to update values
for (let i = 0; i < prices.length; i++) {
prices[i] = prices[i] * 1.1;
}
console.log(prices); // [110, 220, 330] ✅Practical Exercise
Create a file called for-of-loop.js:
// 🎯 For...of Loop Practice
// 1. Student grade report
console.log("=== 📊 Grade Report ===");
let students = [
{ name: "Mihir", marks: 92, attendance: 95 },
{ name: "Priya", marks: 85, attendance: 80 },
{ name: "Rahul", marks: 55, attendance: 70 },
{ name: "Sara", marks: 78, attendance: 90 },
{ name: "Arjun", marks: 40, attendance: 60 },
];
let passed = 0;
let failed = 0;
for (let student of students) {
let grade = student.marks >= 90 ? "A"
: student.marks >= 75 ? "B"
: student.marks >= 60 ? "C"
: "F";
let status = student.marks >= 40 && student.attendance >= 75 ? "Pass ✅" : "Fail ❌";
status === "Pass ✅" ? passed++ : failed++;
console.log(`${student.name.padEnd(8)} | Marks: ${student.marks} | Grade: ${grade} | ${status}`);
}
console.log(`\nTotal Passed: ${passed} | Total Failed: ${failed}`);
// 2. Unique characters in a string
console.log("\n=== 🔡 Unique Characters ===");
let text = "javascript";
let seen = new Set();
for (let char of text) {
seen.add(char);
}
console.log(`String: "${text}"`);
console.log(`Unique characters (${seen.size}): ${[...seen].join(", ")}`);
// 3. Inventory checker
console.log("\n=== 📦 Inventory Check ===");
let inventory = [
{ item: "Laptop", stock: 12, minStock: 5 },
{ item: "Mouse", stock: 3, minStock: 10 },
{ item: "Monitor", stock: 8, minStock: 5 },
{ item: "Keyboard", stock: 1, minStock: 10 },
{ item: "Webcam", stock: 20, minStock: 5 },
];
for (let product of inventory) {
let status = product.stock === 0 ? "OUT OF STOCK 🔴"
: product.stock < product.minStock ? "LOW STOCK 🟡"
: "IN STOCK 🟢";
console.log(`${product.item.padEnd(12)} | Qty: ${String(product.stock).padStart(3)} | ${status}`);
}
// 4. Sentence word analysis
console.log("\n=== 📝 Word Analysis ===");
let sentence = "the quick brown fox jumps over the lazy dog";
let wordList = sentence.split(" ");
let wordLengths = {};
for (let word of wordList) {
let len = word.length;
wordLengths[len] = (wordLengths[len] || 0) + 1;
}
for (let [length, count] of Object.entries(wordLengths).sort()) {
console.log(`${length}-letter words: ${count}`);
}Run it:
node for-of-loop.jsExpected Output:
=== 📊 Grade Report ===
Mihir | Marks: 92 | Grade: A | Pass ✅
Priya | Marks: 85 | Grade: B | Pass ✅
Rahul | Marks: 55 | Grade: C | Fail ❌
Sara | Marks: 78 | Grade: B | Pass ✅
Arjun | Marks: 40 | Grade: F | Fail ❌
Total Passed: 3 | Total Failed: 2
=== 🔡 Unique Characters ===
String: "javascript"
Unique characters (9): j, a, v, s, c, r, i, p, t
=== 📦 Inventory Check ===
Laptop | Qty: 12 | IN STOCK 🟢
Mouse | Qty: 3 | LOW STOCK 🟡
Monitor | Qty: 8 | IN STOCK 🟢
Keyboard | Qty: 1 | LOW STOCK 🟡
Webcam | Qty: 20 | IN STOCK 🟢Key Takeaways
Congratulations! 🎉 You now fully understand the for...of loop in JavaScript.
✅ for...of iterates over the values of any iterable — clean, simple, no index management.
✅ Works on: Arrays, Strings, Sets, Maps, and any iterable.
✅ Does NOT work on plain objects {} — use Object.values(), Object.entries(), or for...in instead.
✅ Need the index? Use array.entries() to get both [index, value] in one step.
✅ break exits early. continue skips the current iteration — both work exactly the same as in other loops.
✅ Cannot directly update array values via for...of — use a classic for loop when you need to mutate the array.
✅ Set + for...of = perfect for deduplication. Map + for...of = perfect for key-value iteration.
Best Practices
- ✅ Prefer
for...ofoverforwhen you only need values — it's cleaner and safer - ✅ Use
entries()when you need both index and value — don't switch toforjust for that - ✅ Use
Object.values()orObject.entries()to usefor...ofon plain objects - ✅ Never use
for...ofto mutate array values — use a classicforloop instead - ✅ Use
for...ofwithSetfor elegant deduplication logic - ✅ Use
for...ofwithMapfor readable key-value iteration - ✅ Don't modify the array you're iterating over — collect changes and apply after
- ✅ Use
constinstead ofletinfor...ofwhen the loop variable won't be reassigned
What's Next?
Great work! 🎉 You've mastered the for...of loop — the cleanest way to work with values in JavaScript.
Next up, let's complete the loops series with the For...in Loop → — designed specifically for iterating over the keys of an object, and the perfect tool for working with dynamic object properties!
Let's keep going! 💪