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 exit —
breakandcontinuework (unlike.forEach()) - Iterables —
for...ofworks 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
| Variant | Iterates over | Best for |
|---|---|---|
for (let i = 0; ...) | Nothing built-in — you control i | Counted loops, index access |
for...of | Values of an iterable | Arrays, strings, Maps, Sets |
for...in | Enumerable property keys | Object 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 32. 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
}Related
- 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