JavaScript Tutorial

For...of Loop in JavaScript: Syntax, Examples and Best Practices

Master the JavaScript for...of loop with clear syntax breakdown, iterating over arrays, strings, Maps, Sets, real-world examples, common mistakes, and best practices.

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
// Mango

Compare 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 iteration
  • of — the keyword that separates the variable from the iterable
  • iterable — 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:

IterableWhat you get
ArrayEach element value
StringEach character
SetEach unique value
MapEach [key, value] pair
NodeListEach 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
// Yellow

Array 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: 82

Array 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 A

Iterating 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: rihiM

Getting 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: 287

break — 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: ₹2500

continue — 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: 75

Real-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: ₹680

Example 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:  45

Example 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,000

for...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!
}
LoopGives youWorks onUse when
forIndex + value (manually)ArraysYou need index control
for...ofValues directlyArrays, Strings, Sets, MapsYou just need values
for...inKeys/property namesObjectsYou 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.js

Expected Output:

=== 📊 Grade Report ===
Mihir    | Marks: 92 | Grade: A | PassPriya    | Marks: 85 | Grade: B | PassRahul    | Marks: 55 | Grade: C | FailSara     | Marks: 78 | Grade: B | PassArjun    | Marks: 40 | Grade: F | FailTotal 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

  1. ✅ Prefer for...of over for when you only need values — it's cleaner and safer
  2. ✅ Use entries() when you need both index and value — don't switch to for just for that
  3. ✅ Use Object.values() or Object.entries() to use for...of on plain objects
  4. ✅ Never use for...of to mutate array values — use a classic for loop instead
  5. ✅ Use for...of with Set for elegant deduplication logic
  6. ✅ Use for...of with Map for readable key-value iteration
  7. ✅ Don't modify the array you're iterating over — collect changes and apply after
  8. ✅ Use const instead of let in for...of when 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! 💪