Junior 5 min · March 05, 2026

JavaScript Loops — Infinite While That Crashed a Dashboard

CPU at 100% on a single core, event loop lag >10s—from a while loop missing its increment.

N
Naren · Founder
Plain-English first. Then code. Then the interview question.
About
 ● Production Incident 🔎 Debug Guide
Quick Answer
  • A loop repeats a block of code until a condition is false or all items are processed.
  • for: Use when you know the exact count (e.g., iterate an array with index).
  • while: Use when the condition depends on runtime state (e.g., waiting for user input).
  • forEach / for...of: Cleaner array iteration, but forEach lacks break/continue.
  • Performance: for is fastest in tight loops; forEach has function call overhead (~50ns per item).
  • Production trap: An infinite while loop freezes the event loop — always ensure the condition changes.
  • Biggest mistake: Using <= instead of < in array loops — leads to undefined access.
Plain-English First

Imagine you're stuffing 100 envelopes for a birthday party. You wouldn't write a separate instruction for each envelope — you'd write one instruction: 'Stuff an envelope, seal it, repeat until all 100 are done.' That's exactly what a loop is in JavaScript. It's one set of instructions that the computer repeats automatically until a condition is met, saving you from writing the same code over and over again.

Every app you've ever used relies on loops. When Instagram loads your feed, a loop runs through every post and renders it on screen. When Spotify builds your playlist, a loop processes every song. When a game checks if you've been hit by an enemy, a loop is running dozens of times per second. Loops are not just a feature of JavaScript — they are one of the fundamental building blocks of everything a program does.

Here's what most tutorials don't tell you: picking the wrong loop can cost you real production issues — from frozen browser tabs to silent data corruption. Understanding when to use each variant is what separates a script from a robust application.

The for Loop — When You Know Exactly How Many Times to Repeat

The for loop is the most common loop you'll write. You reach for it when you know upfront how many times something needs to happen — print 5 messages, process 10 orders, light up 7 checkboxes. Think of it like a strict gym trainer who says: 'Do exactly 10 reps, then stop.' No more, no less.

A for loop has three parts packed into one line, separated by semicolons. First, a starting point — you create a counter variable, usually called i, and set it to 0 (because JavaScript lists start counting from 0, not 1). Second, a condition — the loop keeps running as long as this condition is true. Third, an update — after each loop, you change the counter, usually by adding 1.

When the condition becomes false, JavaScript exits the loop and moves on. That's the whole mechanic. Everything else is just variations on this pattern.

Production reality: The for loop is the only loop that gives you full control — you can decrement, skip steps, or iterate backwards. It's also the fastest loop in JavaScript because it avoids any function call overhead. Use it when performance is critical, like in rendering loops or when processing large arrays.

ForLoopBasics.jsJAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Imagine you're a barista making 5 coffees in a row.
// You don't write five separate instructions — you loop.

const totalCoffees = 5;

for (let coffeeNumber = 1; coffeeNumber <= totalCoffees; coffeeNumber++) {
  // This block runs once for each coffee
  // coffeeNumber starts at 1, goes up by 1 each time, stops after 5
  console.log(`Making coffee number ${coffeeNumber} of ${totalCoffees}`);
}

console.log("All coffees done! Time for a break.");

// ---
// Now let's loop through an actual array of items — a very common real-world use.
const studentNames = ["Alice", "Bob", "Carmen", "David"];

for (let index = 0; index < studentNames.length; index++) {
  // studentNames.length is 4, so index goes 0, 1, 2, 3
  // When index reaches 4, the condition (4 < 4) is FALSE, so the loop stops
  console.log(`Student ${index + 1}: ${studentNames[index]}`);
}
Output
Making coffee number 1 of 5
Making coffee number 2 of 5
Making coffee number 3 of 5
Making coffee number 4 of 5
Making coffee number 5 of 5
All coffees done! Time for a break.
Student 1: Alice
Student 2: Bob
Student 3: Carmen
Student 4: David
Watch Out: Off-by-One Errors
The most common for loop bug is using < vs <=. If your array has 4 items and you write index <= studentNames.length, you'll try to access index 4 — which doesn't exist — and get 'undefined'. Use index < array.length (strictly less than) when looping through arrays. Save <= for when you're counting to a fixed number like in the coffee example above.
Production Insight
Off-by-one errors are the #1 cause of array iteration bugs in production.
They're silent — your code runs, but one element is missing or the last is undefined.
Rule: always use < array.length for array iteration; use <= only for fixed-count loops.
Key Takeaway
Use the for loop when you need explicit control over start, condition, and increment.
It's the most versatile loop, but the three-part syntax makes it error-prone.
Master the off-by-one rule: array length? Use <. Fixed count? Use <=.

The while Loop — When You Don't Know How Many Times to Repeat

The while loop is what you use when you can't predict upfront how many times you'll need to repeat something. The loop just keeps going as long as a condition stays true, and stops the moment it becomes false.

A great real-world analogy: imagine you're fishing. You don't say 'I'll cast exactly 7 times.' You say 'I'll keep casting until I catch a fish.' You don't know if that's 2 casts or 200. That uncertainty is exactly when while is the right tool.

In code, while loops are common for things like: keep asking the user for a password until they get it right, keep downloading data until the file is complete, or keep running a game loop until the player loses. The key discipline with while loops is that something inside the loop must eventually make the condition false — otherwise you get an infinite loop, and your program freezes forever.

Performance note: Because the condition is re-evaluated each iteration, while loops can be slightly slower than for loops if the condition involves a complex expression. But in practice, the overhead is negligible for most applications.

WhileLoopBasics.jsJAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Scenario: A vending machine keeps accepting coins until you've
// inserted enough money for a snack that costs 75 cents.

const snackPrice = 75; // in cents
let totalInserted = 0;  // start with no coins inserted
let coinCount = 0;      // track how many coins were put in

// The condition: keep looping while we haven't paid enough
while (totalInserted < snackPrice) {
  const coinValue = 25; // pretend every coin is a quarter (25 cents)
  totalInserted += coinValue; // add the coin's value to the running total
  coinCount++;               // count one more coin inserted

  console.log(`Inserted coin #${coinCount}: total is now ${totalInserted} cents`);
}

// We only reach this line AFTER the condition (totalInserted < 75) becomes false
console.log(`\nYou inserted ${coinCount} coins. Dispensing your snack! Enjoy!`);

// ---
// Another example: countdown timer
let secondsRemaining = 5;

while (secondsRemaining > 0) {
  console.log(`Launching in ${secondsRemaining}...`);
  secondsRemaining--; // THIS IS CRITICAL — without this, secondsRemaining never changes and we loop forever
}

console.log("🚀 Liftoff!");
Output
Inserted coin #1: total is now 25 cents
Inserted coin #2: total is now 50 cents
Inserted coin #3: total is now 75 cents
You inserted 3 coins. Dispensing your snack! Enjoy!
Launching in 5...
Launching in 4...
Launching in 3...
Launching in 2...
Launching in 1...
🚀 Liftoff!
Watch Out: The Infinite Loop Trap
If you forget to update the variable your condition depends on (like forgetting secondsRemaining-- in the countdown), the condition never becomes false, the loop never stops, and your browser tab will freeze and eventually crash. Always double-check: 'What inside this loop will eventually make my condition false?'
Production Insight
Infinite while loops are a common cause of event loop starvation in Node.js.
Add a safety counter: let safe = 0; while (cond && safe++ < 1e6) { ... }.
This prevents production crashes and gives you a log point to debug.
Key Takeaway
Use while when the number of iterations is unknown at start.
Always mutate the condition variable inside the loop body.
A safety iteration cap is cheap insurance against infinite loops.

forEach and for...of — The Modern, Readable Way to Loop Arrays

Once you understand for loops, JavaScript gives you two cleaner tools specifically designed for looping through arrays and collections: forEach and for...of. They exist because the classic for loop, while powerful, has a lot of visual noise — the counter, the condition, the increment. When all you want to do is 'go through every item in this list,' there's a simpler way.

forEach is a method that lives on every array. You hand it a function, and it calls that function once for each item, automatically passing in the item, its index, and the whole array if you need them. It's expressive — reading it out loud almost sounds like plain English: 'for each order in orders, do this thing.'

for...of is even simpler — it's a loop syntax (like for) but designed for collections. You get the value directly without index gymnastics. Use for...of when you just need the values. Use forEach when you want the built-in index parameter without extra setup. Neither can be 'broken out of' easily with break — use a classic for loop if you need to exit early.

Performance reality: forEach incurs a function call overhead (~50ns per item on V8). For arrays under 10,000 items, it's unnoticeable. For performance-critical hot paths, a for loop is still faster. for...of is also slightly slower than a for loop but more readable.

ModernArrayLoops.jsJAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const pizzaOrders = [
  { customer: "Marco",   topping: "Pepperoni" },
  { customer: "Yuki",    topping: "Mushrooms" },
  { customer: "Priya",   topping: "Extra Cheese" },
  { customer: "Jordan",  topping: "Jalapeños" }
];

// --- forEach ---
// The function receives each item in the array, one at a time.
// 'order' is just the name we give it — you can name it anything.
// 'orderIndex' is automatically provided — it's the position (0, 1, 2...)
console.log("=== forEach Example ===");
pizzaOrders.forEach(function(order, orderIndex) {
  console.log(`Order #${orderIndex + 1}: ${order.customer} wants ${order.topping} pizza`);
});

// --- for...of ---
// Cleaner syntax when you only need the value, not the index.
// It reads almost like plain English: "for each order of pizzaOrders"
console.log("\n=== for...of Example ===");
for (const order of pizzaOrders) {
  // 'order' holds the current item on each iteration
  console.log(`Preparing ${order.topping} pizza for ${order.customer}`);
}

// --- Arrow function shorthand (you'll see this everywhere in real codebases) ---
console.log("\n=== Arrow Function Shorthand ===");
pizzaOrders.forEach((order) => {
  console.log(`Ready: ${order.customer}'s ${order.topping} pizza 🍕`);
});
Output
=== forEach Example ===
Order #1: Marco wants Pepperoni pizza
Order #2: Yuki wants Mushrooms pizza
Order #3: Priya wants Extra Cheese pizza
Order #4: Jordan wants Jalapeños pizza
=== for...of Example ===
Preparing Pepperoni pizza for Marco
Preparing Mushrooms pizza for Yuki
Preparing Extra Cheese pizza for Priya
Preparing Jalapeños pizza for Jordan
=== Arrow Function Shorthand ===
Ready: Marco's Pepperoni pizza 🍕
Ready: Yuki's Mushrooms pizza 🍕
Ready: Priya's Extra Cheese pizza 🍕
Ready: Jordan's Jalapeños pizza 🍕
Pro Tip: Pick the Right Loop for the Job
Use for when you need a counter or need to break early. Use while when you're waiting for an unpredictable condition. Use forEach or for...of when you're iterating an array and want clean, readable code. Defaulting to forEach for all array work is what most professional JavaScript developers actually do in modern codebases.
Production Insight
forEach does not support break, continue, or return to exit early.
If your code reviews show a forEach with a return inside — that return exits only the callback, not the loop.
Trap: developers often add if (condition) return; in forEach expecting early exit, but the loop continues.
Key Takeaway
forEach and for...of are the most readable ways to iterate arrays.
for...of supports break and continue; forEach does not.
Choose forEach when you need the index; choose for...of when you need break.

do...while — The Loop That Always Runs at Least Once

There's one more loop worth knowing: do...while. It's the least common, but it solves a specific problem elegantly. Every other loop checks its condition before running the code block. A do...while checks the condition after. That means the block always executes at least one time, even if the condition starts out false.

When does that matter? Think of a login form. You always want to show the form at least once — you check if the login was successful after the user submits it, not before they've even seen it. Or think of a game's main menu: show it first, then decide whether to keep showing it based on what the player picks.

In practice, do...while is genuinely rare in modern JavaScript. You'll mostly see it in interview questions and legacy code. But understanding it deepens your grasp of how loop conditions work, which makes you sharper with all the other loops too.

Production note: Because the loop body always runs once, do...while is useful for initialization logic that must execute before the condition check. For example, sending an initial request and then deciding whether to retry based on the response.

DoWhileLoop.jsJAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Scenario: A quiz app that always asks at least one question,
// then checks if the player wants to continue.

// We'll simulate the user's responses with an array
const simulatedUserResponses = ["yes", "yes", "no"]; // 'no' means they quit
let responseIndex = 0;
let questionNumber = 0;

do {
  questionNumber++;

  // In a real app, this would be an actual quiz question
  console.log(`Question ${questionNumber}: What is 2 + 2? (Simulated answer: 4)`);

  // Simulate getting a response from the user
  const userWantsToContinue = simulatedUserResponses[responseIndex];
  responseIndex++;

  console.log(`Player said: "${userWantsToContinue}"`);

  // The condition is checked DOWN HERE — after the block already ran
  if (userWantsToContinue !== "yes") {
    console.log("\nPlayer chose to stop. Thanks for playing!");
    break; // exit the loop
  }

} while (responseIndex < simulatedUserResponses.length);

console.log(`Total questions answered: ${questionNumber}`);

// Key point: even if simulatedUserResponses was empty and the condition
// was false from the start, the block inside 'do' would still run once.
Output
Question 1: What is 2 + 2? (Simulated answer: 4)
Player said: "yes"
Question 2: What is 2 + 2? (Simulated answer: 4)
Player said: "yes"
Question 3: What is 2 + 2? (Simulated answer: 4)
Player said: "no"
Player chose to stop. Thanks for playing!
Total questions answered: 3
Interview Gold: for vs while vs do...while
Interviewers love asking: 'What's the difference between while and do...while?' The one-line answer: a while loop might never execute if the condition starts false. A do...while always executes at least once. Nail this distinction and you'll stand out from candidates who only know syntax.
Production Insight
do...while is rarely used in modern JavaScript, so if you see it in a codebase, there's usually a specific reason.
Common production use: retry loops where the first attempt must happen before checking a response.
Trap: forgetting that do...while can become infinite just like while if the condition never changes.
Key Takeaway
do...while guarantees at least one iteration.
Use it when the action must happen before the condition check.
Otherwise, prefer while or for loops for clarity.

The for...in Loop — When to Use and When to Avoid It

JavaScript also provides a for...in loop, but it's designed for iterating over object keys, not arrays. It loops through all enumerable properties of an object, including inherited ones from the prototype chain. This makes it unpredictable for arrays because it returns keys as strings and includes array methods if any have been added to Array.prototype.

The rule of thumb: Never use for...in to iterate arrays. Use it only for plain objects when you need to loop over property names. For arrays, stick with for, for...of, or forEach.

Why it's dangerous for arrays: The iteration order is not guaranteed to be numeric index order. If you or a library has extended Array.prototype, those methods will appear as keys. This leads to subtle bugs that are hard to track down.

ForInLoop.jsJAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// DO NOT DO THIS - for...in on arrays is unreliable
const arr = ['a', 'b', 'c'];
Array.prototype.customMethod = function() {};

for (const key in arr) {
  console.log(key, arr[key]);
  // Output: "0 a", "1 b", "2 c", "customMethod undefined"
}

// CORRECT: Use plain object iteration
const user = { name: 'Alice', role: 'admin', age: 30 };
for (const prop in user) {
  if (user.hasOwnProperty(prop)) {
    console.log(`${prop}: ${user[prop]}`);
  }
}
// Output: "name: Alice", "role: admin", "age: 30"
Output
0 a
1 b
2 c
customMethod undefined
name: Alice
role: admin
age: 30
Never Use for...in for Arrays in Production
for...in iterates over all enumerable properties, including prototype additions. This breaks when any polyfill or library extends Array.prototype. Always use for...of or forEach for arrays.
Production Insight
Production bug: a team used for...in on an array that had a polyfilled Array.prototype.includes. The loop iterated 'includes' as a key, causing the app to crash.
Fix: always use for...of or forEach for arrays.
If you must use for...in for objects, guard with hasOwnProperty.
Key Takeaway
Use for...in only for iterating object keys, not arrays.
Always filter with hasOwnProperty to skip prototype properties.
Stick with for...of or forEach for array iteration.
● Production incidentPOST-MORTEMseverity: high

The Infinite Loop That Brought Down the Dashboard

Symptom
Dashboard stopped responding after 10 minutes of use. CPU pinned at 100% on a single core. Node.js event loop lag exceeded 10 seconds.
Assumption
The team assumed the issue was a database query slowdown and scaled up the DB instance, but the problem persisted.
Root cause
A while loop in a report aggregation function was missing the increment on its counter variable. The condition count < items.length was always true because count never increased. The loop ran indefinitely, blocking the event loop in Node.js (single-threaded).
Fix
Added count++ inside the while loop. Also added a safety break: if (count > 10000) break; to guard against future logic errors. Implemented a maximum iteration guard in the code review checklist.
Key lesson
  • Always ensure the condition variable changes inside a while loop.
  • Add a fail-safe iteration cap (e.g., if (iterations++ > MAX_SAFE) break;) for any unbounded loop.
  • Monitor event loop lag — it's the first signal of a blocked loop in production.
Production debug guideSymptom → Action grid for common loop-related failures in JavaScript4 entries
Symptom · 01
Browser tab freezes / page becomes unresponsive
Fix
Check for infinite loops: use browser debugger to pause execution, look at the call stack. If it's deep in a loop, check the condition. Add a counter and log it to the console.
Symptom · 02
Array element is undefined when iterating
Fix
Off-by-one error: verify loop condition. Did you use <= instead of <? Check if index goes up to array.length - 1. Log the index and value at each iteration.
Symptom · 03
forEach loop exits early unexpectedly or doesn't run
Fix
forEach does not support break or continue. If you need early exit, switch to for or for...of. Also ensure the array is not null or undefined.
Symptom · 04
Node.js process hangs / event loop lag spikes
Fix
Use console.log('loop iteration ' + i) to trace loop progression. If the log stops, the condition never turned false. Add an iteration counter with a max limit as a safety net.
★ Quick Debug Cheat Sheet for JavaScript LoopsCommon symptoms, immediate actions, and commands to diagnose loop issues
Infinite loop (browser freezes)
Immediate action
Open DevTools (F12) → Sources → Pause script execution. Look at current line in call stack.
Commands
Add `console.count('loop')` inside the loop body.
Check condition variable changes: `console.log('counter:', i)` after each iteration.
Fix now
Insert a safety break: if (i > 10000) break; above the loop body.
Accessing array element returns undefined+
Immediate action
Log the length: `console.log('array length:', array.length)`.
Commands
Log the index: `console.log('index:', i, 'value:', array[i])`.
Check loop condition: change `<=` to `<` if using index based loop.
Fix now
Replace i <= array.length with i < array.length in the condition.
forEach does not stop when expected+
Immediate action
Identify that `break` and `continue` are not supported in `forEach`.
Commands
Check if you can use `for...of` instead: `for (const item of array) { if (condition) break; }`.
Alternatively, convert to a `for` loop with `return` as early exit (but `forEach` callback returns, not loop).
Fix now
Replace array.forEach(...) with for (const item of array) { ... } if early break is needed.
Loop Type Comparison
Loop TypeBest Used WhenChecks ConditionWorks with break/continueReadable for Arrays
forYou know the exact count upfrontBefore each iterationYesWorks, but verbose
whileCondition depends on unpredictable stateBefore each iterationYesPossible, but unusual
do...whileBlock must run at least once regardlessAfter each iterationYesRare in practice
forEachIterating every item in an arrayN/A (array-driven)No — use for insteadExcellent — most readable
for...ofIterating values in any iterable collectionN/A (collection-driven)YesExcellent — clean syntax
for...inIterating object keys (not arrays)N/A (property enumeration)YesNever use for arrays

Key takeaways

1
Use a for loop when you know exactly how many iterations you need
it's the most precise and flexible loop, and the only one that natively supports breaking out early with break.
2
Use a while loop when the number of iterations is unknown and depends on a condition that changes during runtime
but always guarantee that something inside the loop will eventually make the condition false.
3
forEach and for...of are the modern, readable choices for array iteration
forEach is ideal when you need the index built in, for...of is cleaner when you only need values; neither supports break, so fall back to for when you need early exit.
4
do...while is the only loop guaranteed to execute at least once
it checks its condition after the block runs, making it perfect for 'show first, check after' scenarios like login forms or game menus.
5
Avoid for...in for arrays
it iterates over prototype properties and has unpredictable order. Use for...of or forEach instead.

Common mistakes to avoid

4 patterns
×

Off-by-one error with array indexes

Symptom
Accessing array[array.length] returns undefined. The last element is never processed, or the loop tries one too many.
Fix
Use < array.length instead of <= array.length in the loop condition. Remember: arrays are zero-indexed, valid indices are 0 to length-1.
×

Infinite loop due to missing variable update in while/do...while

Symptom
Browser tab freezes or Node.js process hangs. CPU usage hits 100% on one core.
Fix
Ensure the condition variable is modified inside the loop. Add a safety break with a max iteration count as a guard.
×

Using `return` or `break` inside forEach expecting early exit

Symptom
Code inside forEach continues to execute for all items even though a condition was met. break causes a SyntaxError; return exits only the callback, not the loop.
Fix
Switch to a for loop or for...of if you need early exit. forEach is designed for processing all items; use it only when you intend to handle every element.
×

Using for...in on arrays

Symptom
Iteration includes unexpected properties like 'toString' or custom prototype methods. Order is not guaranteed.
Fix
Always use for...of, forEach, or a classic for loop for arrays. Reserve for...in for plain objects, and add hasOwnProperty check.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
What is the difference between for...in and for...of in JavaScript, and ...
Q02SENIOR
Can you explain what causes an infinite loop and walk me through how you...
Q03SENIOR
If forEach and a for loop can both iterate an array, why would you ever ...
Q04JUNIOR
What does the `do...while` loop guarantee that `while` does not? Provide...
Q01 of 04SENIOR

What is the difference between for...in and for...of in JavaScript, and why should you avoid for...in when iterating arrays?

ANSWER
for...in iterates over enumerable property names (keys), including inherited ones from the prototype chain. for...of iterates over values of an iterable like an array. for...in on arrays is unreliable because it includes prototype properties, iteration order is not guaranteed, and it converts indices to strings. Always use for...of for array values.
FAQ · 4 QUESTIONS

Frequently Asked Questions

01
What is the most commonly used loop in JavaScript?
02
What's the difference between for...in and for...of in JavaScript?
03
How do I stop a loop early in JavaScript?
04
Which loop is fastest in JavaScript?
🔥

That's JS Basics. Mark it forged?

5 min read · try the examples if you haven't

Previous
Objects in JavaScript
8 / 16 · JS Basics
Next
Conditionals in JavaScript