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

JS for-of.js
const colors = ["red", "green", "blue"];

for (const color of colors) {
  console.log(color.toUpperCase());
}
Output
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:

JS iterables.js
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}`);
}
Output
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:

JS entries.js
const podium = ["Mia", "Leo", "Ava"];

for (const [index, name] of podium.entries()) {
  console.log(`${index + 1}. ${name}`);
}
Output
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:

JS for-in.js
const scores = { math: 91, art: 78, history: 85 };

for (const subject in scores) {
  console.log(subject, "→", scores[subject]);
}
Output
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

JS for-in-array.js
const nums = [10, 20, 30];

for (const i in nums) {
  console.log(i, typeof i);
}
Output
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:

JS object-entries.js
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);
Output
pads: out of stock
total items: 52

Summary

LoopGives youUse on
for…ofValuesArrays, strings, Maps, Sets, NodeLists
for…inKeys (as strings)Plain objects
for…of Object.entries(obj)[key, value] pairsPlain objects — usually the best choice

Try it yourself

Try it yourself
Console output