Day 3 · Concept 07
Loops & iterators
for-of walks values. for-in walks object keys (rarely what you want). Generators produce iterables lazily. The iterator protocol unifies them all.
1 · for-of — the workhorse
// Works on anything iterable: arrays, strings, Maps, Sets, etc.
for (const ch of "hi!") {
console.log(ch);
}
for (const x of [10, 20, 30]) {
console.log(x);
}
const map = new Map([["a", 1], ["b", 2]]);
for (const [k, v] of map) {
console.log(k, v);
}2 · for-in — for object keys only
const counts = { apples: 3, pears: 5 };
for (const key in counts) {
console.log(key, counts[key]);
}
// Never use on arrays — returns indices as strings and walks inherited keys
const arr = [10, 20, 30];
for (const i in arr) {
console.log(typeof i, i); // "string" "0", etc.
}The rule: for-of for arrays and iterables; for-in for plain objects only. Or — better — Object.entries(obj) + for-of.
3 · Array.from — turn anything iterable into an array
// Generate a sequence
console.log(Array.from({ length: 5 }, (_, i) => i * i));
// Iterable → array
console.log(Array.from("abc"));
console.log(Array.from(new Set([1, 2, 2, 3])));4 · Generators — lazy iterables
function* fib() {
let [a, b] = [0, 1];
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
const it = fib();
const first10 = [];
for (let i = 0; i < 10; i++) first10.push(it.next().value);
console.log(first10);The function* + yield pair gives you a paused/resumed function. Useful for infinite or expensive sequences.
5 · Common mistakes
for-inon arrays. Keys are strings; order is engine-dependent (mostly insertion, but don't rely on it). Usefor-of.forEachwithawait.forEachdoesn't await. Usefor-ofwithawaitinside, orPromise.all.- Mutating while iterating. Modifying an array during
for-ofcan skip or repeat elements. Collect indices first or use a copy.
6 · When it clicks
for-offor sequences;Object.entriesfor objects;.map/.filter/.reducewhen you can.Array.from({length: n}, ...)for generating ranges.- Generators are second nature for stream-like data.
Found this useful?