šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
JS MASTER CLASS /// MASTER THE ENGINE /// BUILD LOGIC /// ASYNC PATTERNS /// JS MASTER CLASS /// MASTER THE ENGINE ///

JavaScript Loops: for, for...of, forEach — Iterating Arrays the Right Way - In-Depth Guide

Master every way to loop through arrays in JavaScript: the classic for loop for full control, for...of for clean value extraction, and .forEach() for functional callbacks. Learn why for...in is dangerous on arrays.

⚔ Total XP: 0|šŸ’» javascript XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Core logic.

Quick Quiz //

What is the primary advantage discussed here?


šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Looping is how you process every item in an array without writing repetitive manual code. This lesson compares the classic for loop, the modern for...of loop, and the functional .forEach() method — and explains why for...in should never be used on arrays.

1JavaScript Loops Part 1

<h2>The Need for Iteration</h2><p>Data collections are useless if we can't process them efficiently. Imagine having an array of 500 users and needing to render a profile card for each one.</p><p>Writing out individual commands for all 500 users is impossible. <strong>Loops</strong> are the solution. They allow you to write a single block of code and instruct the JavaScript engine to execute it repeatedly for every item in your collection.</p>

āœ•
—
+
const users = ['Ana', 'Bob', 'Carlos', 'Diana', 'Eve'];

// āŒ Manual — not scalable
console.log(users[0]);
console.log(users[1]);
console.log(users[2]);
// ... 497 more?

// āœ… Loop — handles any length
for (const user of users) {
  console.log(user);
}
localhost:3000

Automation

500 Users
šŸ”
3 Lines of Code

2JavaScript Loops Part 2

<h2>The Classic For Loop</h2><p>The traditional <code>for</code> loop gives you absolute, granular control over your iteration.</p><ul><li><strong>Initializer:</strong> <code>let i = 0</code> sets the starting point.</li><li><strong>Condition:</strong> <code>i &lt; array.length</code> determines when the loop should stop.</li><li><strong>Increment:</strong> <code>i++</code> advances the counter after every cycle.</li></ul><p>By tweaking these three parameters, you can achieve complex iteration patterns.</p>

āœ•
—
+
const colors = ['Red', 'Green', 'Blue', 'Yellow'];

//          ā‘  INIT      ā‘” CONDITION         ā‘¢ INCREMENT
for (let i = 0;   i < colors.length;   i++) {
  console.log(`Index ${i}: ${colors[i]}`);
}

// Output:
// Index 0: Red
// Index 1: Green
// Index 2: Blue
// Index 3: Yellow
localhost:3000

For Loop Anatomy

1. Init: i = 0
2. Cond: i < len
3. Incr: i++

3JavaScript Loops Part 3

<h2>Advanced Control</h2><p>The classic <code>for</code> loop isn't just for moving forward one by one.</p><p>Because you control the math, you can loop backwards by starting at <code>length - 1</code> and decrementing (<code>i--</code>). You can skip elements by stepping by 2 (<code>i += 2</code>). And most importantly, you can exit the loop entirely at any moment using the <code>break</code> keyword if you find what you're looking for early.</p>

āœ•
—
+
const nums = [10, 20, 30, 40, 50];

// Loop BACKWARDS
for (let i = nums.length - 1; i >= 0; i--) {
  console.log(nums[i]); // 50, 40, 30, 20, 10
}

// SKIP every other item (step by 2)
for (let i = 0; i < nums.length; i += 2) {
  console.log(nums[i]); // 10, 30, 50
}

// EXIT EARLY with break
for (let i = 0; i < nums.length; i++) {
  if (nums[i] === 30) break; // stop here
  console.log(nums[i]); // 10, 20
}
localhost:3000

Loop Superpowers

āŖ Backwards: i--
šŸ‡ Skip: i += 2
šŸ›‘ Stop: break

4JavaScript Loops Part 4

<h2>The Modern Standard: for...of</h2><p>While the classic loop is powerful, it's often overly verbose for simple arrays. The <code>for...of</code> loop is the modern standard.</p><p>It abstracts away the index management entirely, extracting the <strong>value</strong> of each element directly into a variable. It prevents "off-by-one" errors and makes your code much easier to read.</p>

āœ•
—
+
const tasks = ['Design UI', 'Write API', 'Deploy'];

// āœ… for...of — clean, direct value access
for (const task of tasks) {
  console.log(task);
}
// 'Design UI'
// 'Write API'
// 'Deploy'

// Works with any iterable: strings, Maps, Sets
for (const char of 'Hello') {
  console.log(char); // H, e, l, l, o
}
localhost:3000

for...of Magic

['Design UI', 'Write API', 'Deploy']
ā¬‡ļø
Direct Value Extraction

5JavaScript Loops Part 5

<h2>The for...in Bug</h2><p>A very common and dangerous mistake is using <code>for...in</code> instead of <code>for...of</code> on an array.</p><p><code>for...in</code> iterates over the <strong>keys</strong> of an object. For arrays, these keys are the indices, but they are returned as <em>Strings</em> (e.g., "0", "1"). If you try to do math with them, you'll end up with string concatenation bugs (e.g., "0" + 1 = "01"). Never use <code>for...in</code> on arrays!</p>

āœ•
—
+
const scores = [85, 92, 78];

// āœ… for...of → VALUES
for (const score of scores) {
  console.log(score);        // 85, 92, 78 (numbers)
  console.log(typeof score); // 'number'
}

// āŒ for...in → KEYS (as strings!)
for (const key in scores) {
  console.log(key);          // '0', '1', '2' (strings!)
  console.log(typeof key);   // 'string'
  console.log(key + 1);      // '01', '11', '21' ← BUG!
}
localhost:3000

The for...in Bug

for...of āžœ Values (85) āœ…
for...in āžœ String Keys ('0') āŒ
'0' + 1 = '01'

6JavaScript Loops Part 6

<h2>Functional Iteration: .forEach()</h2><p>The <code>.forEach()</code> method embraces a functional programming style.</p><p>Instead of setting up a loop structure, you pass a <strong>callback function</strong> to <code>.forEach()</code>. The engine will execute this function once for every element in the array, automatically passing the value, the index, and the original array as arguments to your callback.</p>

āœ•
—
+
const products = ['Laptop', 'Mouse', 'Keyboard'];

// Basic forEach — value only
products.forEach(product => {
  console.log(product);
});

// Full signature: (value, index, array)
products.forEach((product, index, arr) => {
  console.log(`${index + 1}/${arr.length}: ${product}`);
});
// '1/3: Laptop'
// '2/3: Mouse'
// '3/3: Keyboard'
localhost:3000

Functional Callback

Call (Laptop, 0, […])
Call (Mouse, 1, […])
Call (Keyboard, 2, […])

7JavaScript Loops Part 7

<h2>Limitations of .forEach()</h2><p>While <code>.forEach()</code> is elegant, it has a strict limitation: <strong>you cannot break out of it early.</strong></p><p>Using the <code>return</code> keyword inside the callback only exits that specific execution of the callback. The loop will relentlessly continue to process the rest of the array. If you need the ability to short-circuit or break early, use a <code>for...of</code> loop instead.</p>

āœ•
—
+
const nums = [1, 2, 3, 4, 5];

// āŒ Cannot break out of forEach
nums.forEach(n => {
  if (n === 3) return; // skips 3, but 4 and 5 still run
  console.log(n); // 1, 2, 4, 5
});

// āœ… Use for...of when you need break
for (const n of nums) {
  if (n === 3) break; // actually stops the loop
  console.log(n); // 1, 2
}
localhost:3000

No Break in forEach!

return in forEach = Skip 1
break in for...of = Stop Loop

8JavaScript Loops Part 8

<h2>Loops Mastered</h2><p>Congratulations! You now have a complete iteration toolkit.</p><p>You know when to use the classic loop for index control, the <code>for...of</code> loop for clean value extraction, and <code>.forEach()</code> for functional callbacks. These patterns will be used in almost every JavaScript application you build.</p>

āœ•
—
+
localhost:3000

Loops Mastered

9Step-by-Step Breakdown

Imagine you have an array of 500 users. Writing console.log() 500 times is absurd. Loops are the primary mechanism for iteration — they let you run the EXACT SAME code for EVERY item in a collection automatically.

The classic for loop has three parts: INITIALIZER sets your starting index, CONDITION decides when to stop, and INCREMENT advances the counter each time. You get total control over every iteration.

The classic for loop's real power is its precision. You can loop backwards, skip indices by stepping by 2, or exit completely early using break. No other loop gives you this level of index control.

Checkpoint: What part of the classic for loop defines WHEN the iteration should stop?

  • →let i = 0 (initializer)
  • →i < 5 (condition)
  • →i++ (increment)

for...of is the modern standard for array iteration. It extracts the VALUES directly — no index variable, no .length, no off-by-one risk. You should use it for 90% of your daily iteration.

CRITICAL: for...of gives you VALUES. for...in gives you KEYS (as strings). Using for...in on arrays causes subtle bugs because the indices come back as strings, not numbers. This leads to string concatenation bugs instead of math addition.

.forEach() is an array method that embraces functional programming. It takes a CALLBACK function and runs it once per element. The callback automatically receives: the VALUE, the INDEX, and the full ARRAY.

There's an important limitation to .forEach(): you CANNOT break out of it early. Using the 'return' keyword inside the callback only skips that specific callback run — it does NOT stop the overall loop. If you need early exit capabilities, use for...of with a break statement.

Checkpoint: Does .forEach() automatically return a new modified array?

  • →Yes — it transforms the data
  • →No — it returns undefined

Checkpoint: Which loop is preferred for iterating directly over the VALUES of an array in modern JavaScript?

  • →for...in (iterates keys)
  • →for...of (iterates values)

Iteration toolkit complete! Use the classic for loop for total control, for...of for clean value extraction, and .forEach() for functional callbacks. Never use for...in on arrays. Next up: DOM Manipulation.

Level Up šŸš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Loop-Generated Lists Need Semantic Wrappers and Stable Keys

When a loop (for...of, .map(), .forEach()) builds a list of UI elements, the output should be placed inside a semantic `<ul>`/`<ol>` with `<li>` children — a flat sequence of `<div>`s built by a loop gives screen readers no indication it's a list, its length, or each item's position.

SEO Implications

  • 1

    Loops That Run Only After a Client-Side Fetch Can Delay or Hide Content from Crawlers

    If visible page content is generated by looping over data that only arrives after a client-side network request, crawlers that don't wait for that JavaScript to finish may index a blank or partial page. Rendering the looped content server-side avoids this gap entirely.

Best Practices

Default to for...of, Reach for a Classic for Loop Only When You Need the Index

for...of is shorter, avoids off-by-one errors, and works on any iterable. Use the classic for loop only when you specifically need manual index control — backwards iteration, skipping elements, or stopping with break inside a callback-based method that doesn't support it.

Never Use for...in to Iterate Over Arrays

for...in enumerates keys, which for an array are numeric indices returned as strings — mixing them into arithmetic produces string concatenation bugs like '0' + 1 === '01'. Reserve for...in for plain objects, and use for...of or array methods for arrays.

Frequent Bugs

THE BUG

Using `array.forEach()` and expecting `break` or `return` to stop the whole loop early.

THE FIX

`return` inside a forEach callback only exits that single callback invocation — the loop continues over every remaining element regardless. If you need to stop iterating early, use a `for...of` loop or the classic `for` loop, both of which support a real `break`.

THE BUG

Looping over an array with `for...in` and getting unexpected results when doing arithmetic with the loop variable.

THE FIX

`for...in` returns each index as a string, not a number, so `key + 1` concatenates instead of adding (`'2' + 1` becomes `'21'`, not `3`). Use `for...of` (for values) or a classic `for` loop with a numeric counter instead.

Real-World Examples

Rendering a Task List While Stopping at the First Incomplete Item

A project dashboard needed to find and highlight the first incomplete task in an ordered array of tasks, then stop looking — a job unsuited to .forEach() since it can't be short-circuited.

const tasks = [
  { name: 'Design UI', done: true },
  { name: 'Write API', done: false },
  { name: 'Deploy', done: false },
];

let firstIncomplete = null;
for (const task of tasks) {
  if (!task.done) {
    firstIncomplete = task;
    break;
  }
}

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Mutating arrays while iterating over them

// Wrong items.forEach((item, index) => { if (item === 'remove') items.splice(index, 1); }); // Correct const newItems = items.filter(item => item !== 'remove');

The Solution //

Modifying an array's length or contents while looping through it (with a for loop or forEach) can cause elements to be skipped. Use methods like filter() or map() instead.

The Error //

Forgetting to await asynchronous functions

// Wrong const data = fetch('api/data'); console.log(data.json()); // Error // Correct const response = await fetch('api/data'); const data = await response.json();

The Solution //

If a function returns a Promise, you must use 'await' (or .then) to get its resolved value. Otherwise, your variable will hold a Promise object instead of the data.

Lesson Glossary

[01]Iteration

The process of repeating a block of code once for every item in a collection. Loops are the primary mechanism for iteration in JavaScript.

Code Preview
for (const item of arr) { ... }

[02]for Loop

The classic three-part loop structure: initializer (let i = 0), condition (i < n), and increment (i++). Gives full control over index, direction, and early exit.

Code Preview
for (let i = 0; i < arr.length; i++)

[03]for...of

A modern loop that iterates directly over the values of any iterable object (arrays, strings, Maps, Sets). Recommended for 90% of array iteration.

Code Preview
for (const value of arr) { ... }

[04]for...in

A loop that iterates over the enumerable string keys of an object. Should NEVER be used on arrays because it returns indices as strings, causing type-coercion bugs.

Code Preview
for (const key in obj) { ... } // objects only

[05].forEach()

An array method that executes a callback function once for each element. Receives (value, index, array). Returns undefined — cannot use break to exit early.

Code Preview
arr.forEach((val, idx) => { ... })

[06]Callback

A function passed as an argument to another function, to be executed as part of that function's operation. .forEach(), .map(), and .filter() all accept callbacks.

Code Preview
(item, index) => { ... }

[07]break

A statement that immediately exits the current loop. Works in for, for...of, while, and switch — but NOT inside .forEach() callbacks.

Code Preview
if (condition) break;

[08]continue

A statement that skips the rest of the current iteration and jumps to the next one. Works in for and for...of, but in .forEach() you use return instead.

Code Preview
if (condition) continue;

[09]Iterable

Any object that implements the Symbol.iterator protocol, making it compatible with for...of. Built-in iterables: Array, String, Map, Set, NodeList.

Code Preview
for (const x of iterable) { ... }

[10]Off-by-One Error

A common bug where a loop runs one time too many or too few, usually caused by using <= instead of < with .length, or starting at 1 instead of 0.

Code Preview
i <= arr.length // ← bug: accesses undefined

Continue Learning