JavaScript Tutorial

Loops with Arrays in JavaScript: Complete Guide with Examples

Master combining loops with arrays in JavaScript — iterating, searching, transforming, building, and processing collections using for, for...of, forEach, and array methods with real-world examples.

Welcome back! 👋 In the previous lesson, you mastered arrays and their built-in methods. Now let's put arrays and loops together — because in real JavaScript, arrays and loops are inseparable!

Almost everything you do with an array involves some kind of iteration — displaying a list, searching for an item, calculating a total, building a new collection, or processing incoming data. This lesson covers every pattern you'll use in real projects.

Let's dive in!


Why Loops with Arrays?

Arrays store collections of data — but data is only useful when you can work through it. Loops are how you do that.

let students = ["Mihir", "Priya", "Rahul", "Sara", "Arjun"];

// Without a loop — you'd have to write each line manually
console.log(students[0]);
console.log(students[1]);
// ... not practical for 100 students!

// With a loop — handle any size array in 3 lines ✅
for (let student of students) {
  console.log(student);
}

The 4 Main Ways to Loop Over an Array

1. for Loop — When You Need the Index

let fruits = ["Apple", "Banana", "Mango", "Orange"];

for (let i = 0; i < fruits.length; i++) {
  console.log(`${i + 1}. ${fruits[i]}`);
}
// Output:
// 1. Apple
// 2. Banana
// 3. Mango
// 4. Orange

Best when: you need the index, need to loop backwards, or need to modify array elements.


2. for...of — When You Just Need the Value

let fruits = ["Apple", "Banana", "Mango", "Orange"];

for (let fruit of fruits) {
  console.log(fruit);
}
// Output:
// Apple
// Banana
// Mango
// Orange

Best when: you only need the value — cleanest and most readable option.


3. forEach() — Callback Style

let fruits = ["Apple", "Banana", "Mango"];

fruits.forEach((fruit, index) => {
  console.log(`${index + 1}. ${fruit}`);
});

Best when: you want a clean callback style without managing a loop manually.


4. for...of with entries() — Value and Index Together

let fruits = ["Apple", "Banana", "Mango"];

for (let [index, fruit] of fruits.entries()) {
  console.log(`${index + 1}. ${fruit}`);
}

Best when: you need both the index and value in a for...of style.


Side by Side Comparison

let colors = ["Red", "Green", "Blue"];

// 1. for loop
for (let i = 0; i < colors.length; i++) {
  console.log(i, colors[i]); // 0 Red, 1 Green, 2 Blue
}

// 2. for...of
for (let color of colors) {
  console.log(color); // Red, Green, Blue
}

// 3. forEach
colors.forEach((color, i) => console.log(i, color)); // 0 Red, 1 Green, 2 Blue

// 4. for...of + entries()
for (let [i, color] of colors.entries()) {
  console.log(i, color); // 0 Red, 1 Green, 2 Blue
}
LoopIndex?Value?Can break?Best for
forIndex control, mutation
for...ofClean value iteration
forEachCallbacks, side effects
for...of + entries()Index + value cleanly

Common Loop Patterns with Arrays

Pattern 1: Build a New Array

Loop through one array and build another from it.

let prices = [100, 200, 300, 400, 500];
let discounted = [];

for (let price of prices) {
  discounted.push(price * 0.9); // 10% off
}

console.log(discounted); // [90, 180, 270, 360, 450]

Pattern 2: Filter Into a New Array

Loop and collect only items that match a condition.

let scores = [45, 82, 60, 91, 73, 55, 88];
let passing = [];

for (let score of scores) {
  if (score >= 75) {
    passing.push(score);
  }
}

console.log(passing); // [82, 91, 88]

Pattern 3: Accumulate a Total

Loop and keep a running total.

let cart = [
  { name: "Laptop",   price: 55000, qty: 1 },
  { name: "Mouse",    price: 800,   qty: 2 },
  { name: "Keyboard", price: 1500,  qty: 1 },
];

let total = 0;
for (let item of cart) {
  total += item.price * item.qty;
}

console.log(`Total: ₹${total.toLocaleString()}`);
// Output: Total: ₹58,100

Pattern 4: Find the First Match

Loop and stop as soon as you find what you need.

let students = [
  { name: "Mihir", marks: 92 },
  { name: "Priya", marks: 85 },
  { name: "Rahul", marks: 78 },
];

let topper = null;

for (let student of students) {
  if (student.marks > 90) {
    topper = student;
    break; // Stop — no need to continue
  }
}

console.log(topper ? `Topper: ${topper.name}` : "No topper found");
// Output: Topper: Mihir

Pattern 5: Find Max and Min

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(`Max: ${max} 🏆`); // Max: 99 🏆
console.log(`Min: ${min} 📉`); // Min: 45 📉

Pattern 6: Search and Check Existence

let users = ["Mihir", "Priya", "Rahul", "Sara"];
let target = "Rahul";
let found = false;

for (let i = 0; i < users.length; i++) {
  if (users[i] === target) {
    console.log(`✅ Found "${target}" at index ${i}`);
    found = true;
    break;
  }
}

if (!found) console.log(`❌ "${target}" not found`);
// Output: ✅ Found "Rahul" at index 2

Pattern 7: Transform an Array of Objects

let employees = [
  { name: "Mihir", salary: 50000 },
  { name: "Priya", salary: 45000 },
  { name: "Rahul", salary: 60000 },
];

let withBonus = [];

for (let emp of employees) {
  withBonus.push({
    name:   emp.name,
    salary: emp.salary,
    bonus:  emp.salary * 0.1,
    total:  emp.salary * 1.1,
  });
}

for (let emp of withBonus) {
  console.log(`${emp.name.padEnd(8)}: Salary ₹${emp.salary.toLocaleString()} + Bonus ₹${emp.bonus.toLocaleString()} = ₹${emp.total.toLocaleString()}`);
}
// Output:
// Mihir   : Salary ₹50,000 + Bonus ₹5,000 = ₹55,000
// Priya   : Salary ₹45,000 + Bonus ₹4,500 = ₹49,500
// Rahul   : Salary ₹60,000 + Bonus ₹6,000 = ₹66,000

Pattern 8: Loop with continue to Skip Items

let orders = [
  { id: 1, status: "delivered", amount: 1500 },
  { id: 2, status: "cancelled", amount: 800  },
  { id: 3, status: "delivered", amount: 2200 },
  { id: 4, status: "pending",   amount: 600  },
  { id: 5, status: "delivered", amount: 950  },
];

let deliveredTotal = 0;

for (let order of orders) {
  if (order.status !== "delivered") continue;
  deliveredTotal += order.amount;
  console.log(`✅ Order #${order.id}: ₹${order.amount}`);
}

console.log(`\nDelivered Total: ₹${deliveredTotal.toLocaleString()}`);
// Output:
// ✅ Order #1: ₹1500
// ✅ Order #3: ₹2200
// ✅ Order #5: ₹950
// Delivered Total: ₹4,650

Nested Loops with Arrays

Loop Over a 2D Array (Matrix)

let matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
];

for (let row of matrix) {
  let line = "";
  for (let cell of row) {
    line += String(cell).padStart(4);
  }
  console.log(line);
}
// Output:
//    1   2   3
//    4   5   6
//    7   8   9

Loop Over Array of Arrays

let schedule = [
  ["Monday",    ["Math", "Science", "English"]],
  ["Tuesday",   ["History", "Art", "PE"]],
  ["Wednesday", ["Math", "Computer", "Music"]],
];

for (let [day, subjects] of schedule) {
  console.log(`\n📅 ${day}:`);
  for (let subject of subjects) {
    console.log(`   • ${subject}`);
  }
}
// Output:
// 📅 Monday:
//    • Math
//    • Science
//    • English
// ...

Loops vs Array Methods — Which to Use?

Both can solve the same problems. Here's how to decide:

let scores = [85, 92, 78, 60, 95, 55];

// --- TRANSFORM ---
// Loop version
let doubled = [];
for (let s of scores) doubled.push(s * 2);

// Method version — cleaner ✅
let doubled = scores.map(s => s * 2);

// --- FILTER ---
// Loop version
let passing = [];
for (let s of scores) if (s >= 75) passing.push(s);

// Method version — cleaner ✅
let passing = scores.filter(s => s >= 75);

// --- SUM ---
// Loop version
let total = 0;
for (let s of scores) total += s;

// Method version — cleaner ✅
let total = scores.reduce((sum, s) => sum + s, 0);

When to use a for / for...of loop:

  • Complex multi-step logic per item
  • Need to break early (e.g., find first match)
  • Multiple operations per iteration that don't map cleanly to one method
  • Mutating the array elements by index

When to use array methods:

  • Single-purpose transformations (map, filter, reduce)
  • Chaining multiple operations
  • Cleaner, more readable one-liners

Real-World Examples

Example 1: Grade Report Builder

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 },
];

console.log("=".repeat(55));
console.log(`${"Name".padEnd(10)} | ${"Marks".padEnd(6)} | ${"Att%".padEnd(5)} | Grade | Status`);
console.log("=".repeat(55));

let passed = 0, failed = 0;

for (let s of students) {
  let grade  = s.marks >= 90 ? "A" : s.marks >= 75 ? "B" : s.marks >= 60 ? "C" : "F";
  let status = s.marks >= 40 && s.attendance >= 75 ? "Pass ✅" : "Fail ❌";

  status.includes("Pass") ? passed++ : failed++;

  console.log(`${s.name.padEnd(10)} | ${String(s.marks).padEnd(6)} | ${String(s.attendance).padEnd(5)} |   ${grade}   | ${status}`);
}

console.log("=".repeat(55));
console.log(`Results: ${passed} Passed | ${failed} Failed`);

Example 2: Product Search Engine

let products = [
  { id: 1, name: "Laptop",    category: "Electronics", price: 55000 },
  { id: 2, name: "T-Shirt",   category: "Clothing",    price: 799   },
  { id: 3, name: "Phone",     category: "Electronics", price: 18000 },
  { id: 4, name: "Jeans",     category: "Clothing",    price: 1499  },
  { id: 5, name: "Earbuds",   category: "Electronics", price: 2500  },
  { id: 6, name: "Sneakers",  category: "Footwear",    price: 3999  },
];

function searchProducts(products, { category = null, maxPrice = Infinity, keyword = "" }) {
  let results = [];

  for (let product of products) {
    let matchCategory = !category || product.category === category;
    let matchPrice    = product.price <= maxPrice;
    let matchKeyword  = !keyword || product.name.toLowerCase().includes(keyword.toLowerCase());

    if (matchCategory && matchPrice && matchKeyword) {
      results.push(product);
    }
  }

  return results;
}

let results = searchProducts(products, { category: "Electronics", maxPrice: 20000 });

console.log(`Found ${results.length} result(s):`);
for (let p of results) {
  console.log(`  ${p.name.padEnd(12)}${p.price.toLocaleString()}`);
}
// Output:
// Found 2 result(s):
//   Phone        ₹18,000
//   Earbuds      ₹2,500

Example 3: Word Frequency Counter

let text = "the quick brown fox jumps over the lazy dog the fox";
let words = text.split(" ");
let frequency = {};

for (let word of words) {
  frequency[word] = (frequency[word] || 0) + 1;
}

// Sort by frequency and display
let sorted = Object.entries(frequency).sort((a, b) => b[1] - a[1]);

console.log("Word Frequency:");
for (let [word, count] of sorted) {
  let bar = "█".repeat(count);
  console.log(`  ${word.padEnd(8)}: ${bar} (${count})`);
}
// Output:
// Word Frequency:
//   the     : ███ (3)
//   fox     : ██ (2)
//   quick   : █ (1)
// ...

Example 4: Batch Data Processor

let transactions = [
  { id: "T001", type: "credit", amount: 5000 },
  { id: "T002", type: "debit",  amount: 1200 },
  { id: "T003", type: "credit", amount: 3000 },
  { id: "T004", type: "debit",  amount: 800  },
  { id: "T005", type: "credit", amount: 2500 },
  { id: "T006", type: "debit",  amount: 4500 },
];

let totalCredit = 0;
let totalDebit  = 0;
let balance     = 0;

console.log("=== 💳 Transaction History ===");
for (let txn of transactions) {
  if (txn.type === "credit") {
    totalCredit += txn.amount;
    balance     += txn.amount;
    console.log(`${txn.id} ↑ Credit  ₹${txn.amount.toLocaleString().padStart(6)} | Balance: ₹${balance.toLocaleString()}`);
  } else {
    totalDebit += txn.amount;
    balance    -= txn.amount;
    console.log(`${txn.id} ↓ Debit   ₹${txn.amount.toLocaleString().padStart(6)} | Balance: ₹${balance.toLocaleString()}`);
  }
}

console.log("─".repeat(50));
console.log(`Total Credit : ₹${totalCredit.toLocaleString()}`);
console.log(`Total Debit  : ₹${totalDebit.toLocaleString()}`);
console.log(`Final Balance: ₹${balance.toLocaleString()}`);

Common Mistakes

Mistake 1: Modifying an Array While Looping Over It

let items = [1, 2, 3, 4, 5];

// ❌ Pushing inside a for loop — loop never ends!
for (let i = 0; i < items.length; i++) {
  items.push(i * 10); // length keeps growing — infinite loop!
}

// ✅ Collect changes, apply after
let toAdd = [];
for (let item of items) {
  toAdd.push(item * 10);
}
items.push(...toAdd);

Mistake 2: Using forEach and Expecting to break

let numbers = [1, 2, 3, 4, 5];

// ❌ forEach cannot be stopped — break doesn't work!
numbers.forEach(n => {
  if (n === 3) break; // SyntaxError!
  console.log(n);
});

// ✅ Use for...of when you need break
for (let n of numbers) {
  if (n === 3) break; // ✅ Works perfectly
  console.log(n);
}
// Output: 1  2

Mistake 3: Off-by-One with for Loop

let arr = ["A", "B", "C"]; // length = 3, indexes: 0, 1, 2

// ❌ <= goes one too far — reads undefined
for (let i = 0; i <= arr.length; i++) {
  console.log(arr[i]); // A, B, C, undefined ← extra!
}

// ✅ Use <
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]); // A, B, C ✅
}

Mistake 4: Returning Inside forEach Doesn't Exit the Outer Function

function findFirst(arr, target) {
  arr.forEach(item => {
    if (item === target) return item; // ❌ Returns from the callback, NOT findFirst!
  });
  return null; // Always reaches here
}

// ✅ Use for...of with return
function findFirst(arr, target) {
  for (let item of arr) {
    if (item === target) return item; // ✅ Returns from findFirst
  }
  return null;
}

console.log(findFirst(["a", "b", "c"], "b")); // "b" ✅

Practical Exercise

Create a file called loops-with-arrays.js:

// 🎯 Loops with Arrays Practice

// 1. Sales report by region
console.log("=== 📊 Regional Sales Report ===");
let sales = [
  { region: "North", rep: "Mihir",  amount: 85000  },
  { region: "South", rep: "Priya",  amount: 72000  },
  { region: "North", rep: "Rahul",  amount: 91000  },
  { region: "East",  rep: "Sara",   amount: 68000  },
  { region: "South", rep: "Arjun",  amount: 79000  },
  { region: "East",  rep: "Neha",   amount: 55000  },
  { region: "North", rep: "Dev",    amount: 63000  },
];

let regionTotals = {};
let topRep = sales[0];

for (let sale of sales) {
  regionTotals[sale.region] = (regionTotals[sale.region] || 0) + sale.amount;
  if (sale.amount > topRep.amount) topRep = sale;
}

for (let [region, total] of Object.entries(regionTotals)) {
  console.log(`  ${region.padEnd(8)}: ₹${total.toLocaleString()}`);
}
console.log(`\n🏆 Top Performer: ${topRep.rep} (${topRep.region}) — ₹${topRep.amount.toLocaleString()}`);


// 2. Playlist manager
console.log("\n=== 🎵 Playlist Manager ===");
let playlist = [
  { title: "Blinding Lights",   artist: "The Weeknd",  duration: 200 },
  { title: "Shape of You",      artist: "Ed Sheeran",  duration: 234 },
  { title: "Levitating",        artist: "Dua Lipa",    duration: 203 },
  { title: "Stay",              artist: "Kid LAROI",   duration: 141 },
  { title: "Peaches",           artist: "Justin B.",   duration: 198 },
];

let totalDuration = 0;

for (let [i, song] of playlist.entries()) {
  let mins = Math.floor(song.duration / 60);
  let secs = String(song.duration % 60).padStart(2, "0");
  totalDuration += song.duration;
  console.log(`  ${String(i + 1).padStart(2)}. ${song.title.padEnd(22)} ${song.artist.padEnd(15)} ${mins}:${secs}`);
}

let totalMins = Math.floor(totalDuration / 60);
let totalSecs = String(totalDuration % 60).padStart(2, "0");
console.log(`\n  Total duration: ${totalMins}:${totalSecs}`);


// 3. Inventory low-stock alert
console.log("\n=== 📦 Low Stock Alerts ===");
let inventory = [
  { name: "Laptop",    stock: 12, minStock: 5  },
  { name: "Mouse",     stock: 2,  minStock: 10 },
  { name: "Monitor",   stock: 8,  minStock: 5  },
  { name: "Keyboard",  stock: 1,  minStock: 10 },
  { name: "Webcam",    stock: 20, minStock: 5  },
  { name: "Headset",   stock: 3,  minStock: 8  },
];

let alerts = [];

for (let item of inventory) {
  if (item.stock < item.minStock) {
    alerts.push(item);
    console.log(`  ⚠️  ${item.name.padEnd(12)}: Only ${item.stock} left (min: ${item.minStock})`);
  }
}

console.log(alerts.length === 0
  ? "  ✅ All items are sufficiently stocked."
  : `\n  ${alerts.length} item(s) need restocking.`
);

Run it:

node loops-with-arrays.js

Expected Output:

=== 📊 Regional Sales Report ===
  North   : ₹2,39,000
  South   : ₹1,51,000
  East    : ₹1,23,000

🏆 Top Performer: Rahul (North) — ₹91,000

=== 🎵 Playlist Manager ===
   1. Blinding Lights        The Weeknd      3:20
   2. Shape of You           Ed Sheeran      3:54
   ...
  Total duration: 16:16

=== 📦 Low Stock Alerts ===
  ⚠️  Mouse       : Only 2 left (min: 10)
  ⚠️  Keyboard    : Only 1 left (min: 10)
  ⚠️  Headset     : Only 3 left (min: 8)

  3 item(s) need restocking.

Key Takeaways

Congratulations! 🎉 You now know how to combine loops and arrays to solve real-world problems.

4 ways to loop over arraysfor, for...of, forEach, for...of + entries().

Choose the right loop:

  • Need index control or mutation → for
  • Just need values → for...of
  • Callback style, no break needed → forEach
  • Both index and value cleanly → for...of + entries()

8 key patterns — build, filter, accumulate, find first, max/min, search, transform, skip with continue.

break exits early — for and for...of support it. forEach does not.

continue skips the current iteration — works in for and for...of.

Loops vs methods — use map, filter, reduce for clean single-purpose transformations. Use loops for complex multi-step logic.

Never modify an array while looping over it — collect changes and apply after.


Best Practices

  1. ✅ Use for...of as your default loop for arrays — it's clean and readable
  2. ✅ Use for when you need the index or need to mutate elements directly
  3. ✅ Use forEach for side effects — logging, DOM updates — never when you need break
  4. ✅ Use break to exit early — don't keep iterating after you have your answer
  5. ✅ Use continue to skip unwanted items — cleaner than deep nesting with if
  6. ✅ Never modify the array while looping — collect changes and apply after
  7. ✅ Prefer map, filter, reduce for transformations — loops for complex logic
  8. ✅ Use return (not break) inside forEach — but remember it only exits the callback

What's Next?

Excellent work! 🎉 You now know how to loop over arrays in every possible way and apply real patterns to real data.

Next up, let's explore three of the most powerful array methods in JavaScript in depth:

Map, Filter and Reduce → — transform, select, and compute from arrays like a professional developer!

Let's keep going! 💪