for...of vs for...in: Which Loop for Which Job
for...of gives you the values of an array. for...in gives you the keys of an object, as strings. Mix them up and you get indexes instead of items, or worse.
for...of gives you the values of an array (or anything you can loop over). for...in gives you the keys of an object, as strings. Use for...of for arrays. Use for...in, or better Object.entries, for objects. Mix them up and you get positions instead of items, strings instead of numbers, and sometimes keys you never added.
Skip ahead: If you only need the rule, you have it. "Looping over an object properly" is the part worth reading.
Same array, two loops
const items = ["rice", "eggs", "coffee"];
for (const item of items) {
console.log("of:", item);
}
for (const key in items) {
console.log("in:", key, typeof key);
}
of: rice
of: eggs
of: coffee
in: 0 string
in: 1 string
in: 2 string
for...of gave the items. for...in gave the positions, and as strings. "0", not 0.
Why for...in on an array is a trap
The string keys cause bugs the moment you do math with them:
const items = ["rice", "eggs", "coffee"];
for (const i in items) {
console.log(i + 1);
}
01
11
21
You wanted 1, 2, 3. You got text glued together, because i is a string.
It gets worse. for...in also visits any extra properties someone added to the array, and properties inherited from a modified prototype (old libraries did this). The order is also not something you should rely on for arrays. for...of has none of these problems.
⚠ Warning: If you see for (const i in someArray) in code you're fixing, assume it's a bug until proven otherwise. Replace it with for...of, or with for (const [i, item] of someArray.entries()) if you need the position too.
When you need the position
entries() gives you both, with the position as a real number:
const items = ["rice", "eggs", "coffee"];
for (const [i, item] of items.entries()) {
console.log(`${i + 1}. ${item}`);
}
1. rice
2. eggs
3. coffee
A classic for (let i = 0; i < items.length; i++) works too. Use it when you need to skip around or go backwards.
for...of on strings and other things
for...of works on anything "iterable": arrays, strings, Map, Set, NodeList from querySelectorAll.
for (const ch of "Hi!") {
console.log(ch);
}
H
i
!
for (const button of document.querySelectorAll("button")) {
button.disabled = true;
}
It does not work on a plain object:
const product = { name: "Coffee", price: 95 };
try {
for (const x of product) {}
} catch (error) {
console.log(error.message);
}
product is not iterable
That's the error you get when you use for...of on an object by mistake.
Looping over an object properly
for...in is meant for objects:
const product = { name: "Coffee", price: 95 };
for (const key in product) {
console.log(key, product[key]);
}
name Coffee
price 95
That works. But Object.entries is usually clearer, and it only gives the object's own keys, not inherited ones:
const product = { name: "Coffee", price: 95 };
for (const [key, value] of Object.entries(product)) {
console.log(`${key}: ${value}`);
}
console.log(Object.keys(product), Object.values(product));
name: Coffee
price: 95
[ 'name', 'price' ] [ 'Coffee', 95 ]
Object.keys gives an array of keys, Object.values an array of values, Object.entries an array of [key, value] pairs. Once you have an array, you can use for...of and every array method. That's why I'd default to Object.entries and skip for...in entirely. Not because for...in is wrong on objects, but because one loop style for everything means one less thing to get wrong.
💡 Tip: If you can't remember which is which, don't try. Remember this instead: arrays, of. Objects, Object.entries, then of. You never need for...in to get work done.
Quick reference
- Array, need the items:
for (const item of array) - Array, need position and item:
for (const [i, item] of array.entries()) - Object, need keys and values:
for (const [key, value] of Object.entries(obj)) for...in: objects only, and only if you know why you're not usingObject.entries
Search your code for in inside a for (. How many of them loop over an array?
About
What for...of and for...in loop over, why for...in on an array is a trap, and how to loop over an object properly. After this, you pick the right loop the first time.
- Responsible
- John G
- Last Update
- 09/04/2026
- Reading Time
- 4 min
Reviews
Sign in to write a reviewComments (0)
Sign in to commentNo comments yet.