for…of & for…in
Two loop forms remove the bookkeeping of a counter. for…of visits each value in an array, string or other collection; for…in visits each property name of an object. They look alike but do very different jobs.
for…of: loop over values
const colors = ["red", "green", "blue"]; for (const color of colors) { console.log(color.toUpperCase()); }
RED GREEN BLUE
No index variable, no .length, no off-by-one mistakes. Because each iteration gets a fresh variable, you can use const.
for…of works on any iterable — something that can produce values one by one. That includes strings, Map, Set (lesson 34) and many browser collections:
for (const letter of "hey") { console.log(letter); } const prices = new Map([["tea", 3], ["cake", 4.5]]); for (const [item, price] of prices) { console.log(`${item}: $${price}`); }
h e y tea: $3 cake: $4.5
Getting the index too
If you need both position and value, loop over array.entries(), which yields [index, value] pairs:
const podium = ["Mia", "Leo", "Ava"]; for (const [index, name] of podium.entries()) { console.log(`${index + 1}. ${name}`); }
1. Mia 2. Leo 3. Ava
The [index, name] syntax is destructuring, covered in lesson 33.
for…in: loop over property names
for…in visits the keys (property names) of an object:
const scores = { math: 91, art: 78, history: 85 }; for (const subject in scores) { console.log(subject, "→", scores[subject]); }
math → 91 art → 78 history → 85
You get the key, then use bracket notation scores[subject] to read the value.
Don't use for…in on arrays
const nums = [10, 20, 30]; for (const i in nums) { console.log(i, typeof i); }
0 string 1 string 2 string
The "indexes" arrive as strings, so arithmetic like i + 1 gives "01". for…in can also pick up extra properties added to the array or inherited from its prototype. For arrays, use for…of, a classic for loop, or array methods.
A cleaner way to loop over objects
Modern code often converts an object to an array first with Object.keys, Object.values or Object.entries, then uses for…of. This only includes the object's own properties, never inherited ones:
const stock = { pens: 12, pads: 0, clips: 40 }; for (const [item, count] of Object.entries(stock)) { if (count === 0) console.log(`${item}: out of stock`); } const total = Object.values(stock).reduce((sum, n) => sum + n, 0); console.log("total items:", total);
pads: out of stock total items: 52
Summary
| Loop | Gives you | Use on |
|---|---|---|
for…of | Values | Arrays, strings, Maps, Sets, NodeLists |
for…in | Keys (as strings) | Plain objects |
for…of Object.entries(obj) | [key, value] pairs | Plain objects — usually the best choice |