for...of and for...in

Understand the difference between for...of and for...in, and know exactly which one to reach for when iterating over arrays versus objects.

JavaScript has two specialized loop forms built for iteration: for...of, which walks through the values of an iterable like an array or string, and for...in, which walks through the enumerable property keys of an object. Confusing the two is one of the most common beginner mistakes.

for...of: iterating values

for...of iterates over the values produced by an iterable — arrays, strings, Maps, Sets, and anything else that implements the iterable protocol. On each pass, the loop variable is bound directly to the next value, not an index or key.

Because it works on the values themselves, for...of is the natural choice whenever you want to process each element of an array or each character of a string, without needing to manage an index variable manually.

for...in: iterating keys

for...in iterates over the enumerable property keys (as strings) of an object, including keys inherited through its prototype chain. On each pass, the loop variable is bound to a key name, and you use that key to look up the corresponding value with bracket notation.

for...in was designed for plain objects, where there is no numeric index to iterate over — only named properties.

Why for...in is risky on arrays

Arrays are technically objects with numeric-looking string keys ("0", "1", "2", ...), so for...in will technically work on them — but it iterates over keys as strings, in an order that is not strictly guaranteed by the specification for all cases, and it will also pick up any custom, non-index properties someone added to the array or its prototype.

For these reasons, for...of (or array methods like forEach and map) is strongly preferred for arrays, and for...in should be reserved for plain objects.

Choosing the right one

The simplest rule: use for...of when you care about values from something ordered and iterable (arrays, strings, Sets, Maps); use for...in when you care about the named keys of a plain object. If you are ever unsure, ask yourself whether you are looping over a list of items (for...of) or the properties of a single object (for...in).

• for...of → values: arrays, strings, Sets, Maps, any iterable • for...in → keys: plain objects (and, with caveats, arrays — but avoid this)

for...of vs for...in

for...of gives you the value directly — no lookup needed. for...in gives you the key, so you must use obj[key] to get the value. for...of works only on iterables; using it on a plain object throws a TypeError.

// for...of — iterates VALUES of an iterable
const colors = ["red", "green", "blue"];
for (const color of colors) {
  console.log(color);
}

// for...in — iterates KEYS of an object
const user = { name: "Ana", age: 30 };
for (const key in user) {
  console.log(key, "=", user[key]);
}

Code Examples

Each pass of the loop binds fruit directly to the next value in the array — no index bookkeeping is needed to access each item. Expected result: APPLE BANANA CHERRY for (const fruit of fruits) gives the actual string value each time, not its index.

for...in gives back each property name as a string ("title", "price", "inStock"); the value has to be looked up explicitly with product[key], since the loop variable itself only ever holds the key. Expected result: title: Keyboard price: 49.99 inStock: true product[key] performs the lookup — for...in never hands you the value directly.

Common mistake: Using for...in on the array ["apple", "banana", "cherry"] instead of for...of would give you the indexes "0", "1", "2" as strings, not the fruit values — a common source of confusion.

const fruits = ["apple", "banana", "cherry"];

for (const fruit of fruits) {
  console.log(fruit.toUpperCase());
}
const product = { title: "Keyboard", price: 49.99, inStock: true };

for (const key in product) {
  console.log(`${key}: ${product[key]}`);
}

for...of vs for...in

for...of always yields values from an iterable; for...in always yields key names — using the wrong one on the wrong data structure is a frequent source of bugs.

const arr = ["a", "b", "c"];

for...of arr  →  "a", "b", "c"        (VALUES)
for...in arr  →  "0", "1", "2"        (KEYS, as strings — avoid on arrays)

const obj = { x: 1, y: 2 };

for...in obj  →  "x", "y"              (KEYS — correct use)
for...of obj  →  TypeError: obj is not iterable

Important Rules

for...of iterates values and requires an iterable (arrays, strings, Maps, Sets); it throws on plain objects.

for...in iterates enumerable key names (as strings) and is meant for plain objects.

Using for...in on an array gives string index keys and can also pick up inherited/custom properties — prefer for...of or array methods instead.

Inside for...in, always access the value with obj[key], never the key itself as if it were the value.

Where this shows up

for...of is everywhere array processing happens — rendering lists, summing totals, transforming data. for...in shows up when inspecting configuration objects or debugging an object's shape, though modern code often prefers Object.keys/values/entries combined with for...of or array methods for more predictable, array-based iteration.

for (const i in numbers) { total += numbers[i]; // i is a STRING here, e.g. "0", "1" } for (const n of numbers) { total += n; } for...in on an array gives back string indexes, not numbers, and does not guarantee array-appropriate ordering the way a real array iteration does — for...of is the correct, simpler tool for summing array values.

for (const value of myObject) {... } for (const key in myObject) { const value = myObject[key];... }

Plain objects are not iterable by default, so for...of throws "myObject is not iterable" — use for...in for objects, or Object.entries(myObject) with for...of if you want both key and value together.

[Multiple Choice] What does the loop variable represent in a for...in loop over an object? A. The value of each property B. The key (property name) of each property C. The index of each property D. The object itself

B. The key (property name) of each property — for...in binds the loop variable to each enumerable property key (as a string); you must use obj[key] to retrieve the corresponding value.

[True / False] for...of can be used directly on a plain object like { a: 1, b: 2 } without error. A. True B. False

B. False — False. Plain objects do not implement the iterable protocol, so using for...of on one throws a TypeError. Use for...in, or Object.entries()/Object.keys()/Object.values() with for...of instead.

Given const scores = { math: 90, science: 85, art: 95 }, write a for...in loop that logs each subject and score, and separately write a for...of loop over const subjects = ["math", "science", "art"] that logs each subject in uppercase.

const scores = { math: 90, science: 85, art: 95 }; for (const key in scores) { console.log(key, scores[key]); } const subjects = ["math", "science", "art"]; for (const subject of subjects) { console.log(subject.toUpperCase()); }

For the object, remember you need scores[key] to get the value. For the array, the loop variable is already the value.