Skip to Content

for

The classic loop. Comes in three flavors: C-style for, for...of for values, and for...in for keys.

When to use it

  • Counted iteration — run something N times
  • Index access — when you need the position, not just the value
  • Early exitbreak and continue work (unlike .forEach())
  • Iterablesfor...of works on arrays, strings, maps, sets, NodeLists

Anatomy

// C-style — full control over start, end, and step for (let i = 0; i < 5; i++) { i // 0, 1, 2, 3, 4 } // for...of — iterate over values of any iterable for (const item of [10, 20, 30]) { item // 10, 20, 30 } // for...in — iterate over keys (property names) of an object for (const key in { a: 1, b: 2 }) { key // 'a', 'b' }

At a glance

VariantIterates overBest for
for (let i = 0; ...)Nothing built-in — you control iCounted loops, index access
for...ofValues of an iterableArrays, strings, Maps, Sets
for...inEnumerable property keysObject keys (avoid on arrays)

1. Simple — loop N times

for (let i = 0; i < 3; i++) { console.log(`Step ${i + 1}`) } // Step 1 // Step 2 // Step 3

2. Intermediate — for…of with destructuring

const users = [ { name: 'Alice', role: 'admin' }, { name: 'Bob', role: 'user' }, ] for (const { name, role } of users) { console.log(`${name} is ${role}`) } // Alice is admin // Bob is user // works on strings too — each character is a value for (const char of 'hello') { char // 'h', 'e', 'l', 'l', 'o' } // works on Map entries const map = new Map([['a', 1], ['b', 2]]) for (const [key, val] of map) { console.log(key, val) // 'a' 1, 'b' 2 }

3. Advanced — break and continue

// find the first match and stop — can't do this with forEach const items = ['apple', 'banana', 'cherry', 'date'] let found = null for (const item of items) { if (item.startsWith('c')) { found = item break // stop immediately — no wasted iterations } } found // 'cherry' // skip specific iterations for (let i = 0; i < 10; i++) { if (i % 3 === 0) continue // skip multiples of 3 console.log(i) // 1, 2, 4, 5, 7, 8 }

Gotchas

for…in on arrays iterates keys, not values

const arr = ['a', 'b', 'c'] for (const x in arr) { x // '0', '1', '2' — string keys, not values! } // use for...of for array values for (const x of arr) { x // 'a', 'b', 'c' }

let vs var in the initializer

// var leaks into the outer scope and shares one binding for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0) // 3, 3, 3 — all see the same i } // let creates a new binding per iteration for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0) // 0, 1, 2 — each closure captures its own i }

  • while — loop when you don’t know the count upfront
  • .forEach() — array method alternative (no break/continue)
  • .map() — when you need a transformed array back, not just side effects
Last updated on