# JavaScript for...of vs for...in: Differences and Use Cases

Source: https://devdocs10.com/articles/javascript/js-forof-forin  
By Murat Bo · Published 2026-07-03 · DevDocs10 (https://devdocs10.com)

JavaScript has two loop forms that look similar but solve different problems: `for...of` and `for...in`. This article explains what each loop does, how they behave on arrays, objects, strings, and other iterable values, and how to choose the right one without getting subtle bugs.

> **Quick answer:** Use `for...of` to loop over values in an iterable such as an array, string, set, or map. Use `for...in` to loop over enumerable property names on an object, especially when you need keys rather than values.

> **Difficulty:** Beginner
>
> **You'll understand this better if you know:** basic JavaScript variables, arrays and objects, and how `for` loops work at a simple level.

## 1. What Are for...of and for...in?

`for...of` and `for...in` are both loop statements, but they iterate over different things.

- `for...of` gives you each value from an iterable.
- `for...in` gives you each enumerable property name, usually a key or index.
- `for...of` works with arrays, strings, maps, sets, and other iterable objects.
- `for...in` is mainly for objects when you need to inspect keys.

In practice, beginners often mix them up because both use the same loop shape. The important difference is what each loop returns to you.

## 2. Why This Comparison Matters

Choosing the wrong loop can lead to confusing output, accidental traversal of inherited properties, or code that works in one case but fails in another.

`for...of` is usually the better choice for arrays because it is simpler and reads like “give me each item.” `for...in` is useful when you need object keys, but it is not a general-purpose array loop.

Knowing the difference also helps you avoid common mistakes such as looping over array indexes when you wanted values, or trying to use `for...of` on a plain object.

## 3. Basic Syntax

### for...of syntax

`for...of` reads values from an iterable one at a time. The loop variable receives the current value directly.

```javascript
const numbers = [10, 20, 30];

for (const number of numbers) {
  console.log(number);
}
```

Output (tested with Node 24.21.0):

```text
10
20
30
```

Here, `number` is each array value: 10, then 20, then 30.

### for...in syntax

`for...in` loops over property names. On arrays, those property names are usually indexes written as strings.

```javascript
const user = {
  name: "Ava",
  role: "admin"
};

for (const key in user) {
  console.log(key, user[key]);
}
```

Output (tested with Node 24.21.0):

```text
name Ava
role admin
```

Here, `key` becomes `name` and `role`, not the values `Ava` and `admin`.

## 4. Step-by-Step Examples

### Example 1: Looping over an array with for...of

When you want the items in an array, `for...of` is usually the cleanest option.

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

for (const fruit of fruits) {
  console.log(fruit);
}
```

Output (tested with Node 24.21.0):

```text
apple
banana
cherry
```

This prints each fruit value directly. You do not need to manually access indexes.

### Example 2: Looping over array indexes with for...in

`for...in` can loop over array indexes, but that is usually not the best choice unless you need the index as a property name.

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

for (const index in fruits) {
  console.log(index, fruits[index]);
}
```

Output (tested with Node 24.21.0):

```text
0 apple
1 banana
2 cherry
```

This works, but the loop variable is a string index like `"0"`, not the value itself. For arrays, `for...of` is usually easier to read.

### Example 3: Looping over object properties with for...in

Plain objects do not implement iteration in the same way arrays do, so `for...in` is a natural fit when you need keys.

```javascript
const profile = {
  name: "Mina",
  country: "Canada",
  active: true
};

for (const key in profile) {
  console.log(key + ":", profile[key]);
}
```

Output (tested with Node 24.21.0):

```text
name: Mina
country: Canada
active: true
```

This is useful for printing key-value pairs, validating object fields, or building summaries.

### Example 4: Looping over a string with for...of

Strings are iterable, so `for...of` can read each character directly.

```javascript
const word = "code";

for (const character of word) {
  console.log(character);
}
```

Output (tested with Node 24.21.0):

```text
c
o
d
e
```

This prints `c`, `o`, `d`, and `e`. The same loop is much less natural with `for...in` because you would get string indexes instead of letters.

## 5. Practical Use Cases

- Use `for...of` when processing array items such as shopping cart products, search results, or API response lists.
- Use `for...of` to walk through a `Map` or `Set` when you want values or entries.
- Use `for...in` when inspecting object fields such as form data, settings, or configuration objects.
- Use `for...in` when you need property names to build dynamic labels or compare keys.
- Use `for...of` for text processing tasks where each character matters.

## 6. Common Mistakes

### Mistake 1: Using for...of on a plain object

`for...of` only works on iterable values. A plain object is not iterable by default, so the loop fails.

**Problem:** This code tries to iterate over an object with `for...of`, which causes a `TypeError: object is not iterable`.

```javascript
const user = { name: "Ava", role: "admin" };

for (const entry of user) {
  console.log(entry);
}
```

Output (tested with Node 24.21.0):

```text
Uncaught TypeError: user is not iterable
```

**Fix:** Use `for...in` for keys, or convert the object to an array with `Object.entries()` if you want key-value pairs.

```javascript
const user = { name: "Ava", role: "admin" };

for (const key in user) {
  console.log(key, user[key]);
}

for (const [key, value] of Object.entries(user)) {
  console.log(key, value);
}
```

Output (tested with Node 24.21.0):

```text
name Ava
role admin
name Ava
role admin
```

The corrected version works because the loop matches the data structure being used.

### Mistake 2: Expecting for...in to give array values

Many beginners use `for...in` on arrays and then wonder why they get indexes instead of the items themselves.

**Problem:** This code logs array indexes like `0` and `1`, not the actual values.

```javascript
const numbers = [5, 10, 15];

for (const item in numbers) {
  console.log(item);
}
```

Output (tested with Node 24.21.0):

```text
0
1
2
```

**Fix:** Use `for...of` when you need the array values.

```javascript
const numbers = [5, 10, 15];

for (const item of numbers) {
  console.log(item);
}
```

Output (tested with Node 24.21.0):

```text
5
10
15
```

The fixed version is clearer and avoids treating array indexes like data values.

### Mistake 3: Forgetting that for...in can see inherited properties

`for...in` walks enumerable properties, including ones inherited through the prototype chain. That can be surprising if you only want an object’s own properties.

**Problem:** This code may print inherited properties if they are enumerable, which can produce unexpected output or duplicate work.

```javascript
const base = { shared: "yes" };
const child = Object.create(base);
child.own = "value";

for (const key in child) {
  console.log(key);
}
```

Output (tested with Node 24.21.0):

```text
own
shared
```

**Fix:** Filter with `Object.hasOwn()` when you only want properties that belong directly to the object.

```javascript
const base = { shared: "yes" };
const child = Object.create(base);
child.own = "value";

for (const key in child) {
  if (Object.hasOwn(child, key)) {
    console.log(key);
  }
}
```

Output (tested with Node 24.21.0):

```text
own
```

The corrected version avoids accidental traversal of inherited properties.

## 7. Best Practices

### Prefer for...of for arrays and other iterables

When you want values, `for...of` is easier to read and less error-prone than looping by index or using `for...in`.

```javascript
const names = ["Lia", "Noah", "Omar"];

for (const name of names) {
  console.log(name);
}
```

Output (tested with Node 24.21.0):

```text
Lia
Noah
Omar
```

This style directly communicates that the loop is about values, not indexes.

### Use for...in only when you actually need keys

If you need to inspect property names or build a dynamic lookup, `for...in` is appropriate. Otherwise, consider `Object.keys()` or `Object.entries()` for clearer intent.

```javascript
const settings = { theme: "dark", fontSize: 16 };

for (const key in settings) {
  if (Object.hasOwn(settings, key)) {
    console.log(key, settings[key]);
  }
}
```

Output (tested with Node 24.21.0):

```text
theme dark
fontSize 16
```

Adding the ownership check keeps the loop focused on the object’s own data.

### Remember that array indexes from for...in are strings

If you use `for...in` on an array, the loop variable is a string key. That can matter when you compare or format values.

```javascript
const letters = ["a", "b", "c"];

for (const index in letters) {
  console.log(Number(index) + 1, letters[index]);
}
```

Output (tested with Node 24.21.0):

```text
1 a
2 b
3 c
```

This makes the string nature of the index explicit, but for arrays you still usually want `for...of` instead.

## 8. Limitations and Edge Cases

- `for...of` requires an iterable, so plain objects do not work unless converted with `Object.keys()`, `Object.values()`, or `Object.entries()`.
- `for...in` can enumerate inherited enumerable properties, which may surprise you when using objects created with prototypes.
- `for...in` on arrays does not guarantee numeric ordering in the way many developers expect for data processing tasks; it is not meant as an array-value loop.
- Sparse arrays can behave differently from dense arrays, and `for...in` may skip holes because holes are not real properties.
- Strings with surrogate pairs or certain Unicode characters may not behave the way you expect if you assume each visible symbol is one code unit; `for...of` iterates string code points more naturally than index-based loops.
- Neither loop is ideal for asynchronous work by itself; if you need controlled async flow, consider `for...of` with `await` inside an `async` function rather than using `forEach`.

## 9. Practical Mini Project

Here is a small utility that prints a summary of a grocery list object and its items. It uses `for...in` for object keys and `for...of` for array values.

```javascript
const shoppingList = {
  fruits: ["apple", "banana"],
  vegetables: ["carrot", "spinach"],
  drinks: ["water", "tea"]
};

for (const category in shoppingList) {
  if (Object.hasOwn(shoppingList, category)) {
    console.log(category + ":");

    for (const item of shoppingList[category]) {
      console.log("- " + item);
    }
  }
}
```

Output (tested with Node 24.21.0):

```text
fruits:
- apple
- banana
vegetables:
- carrot
- spinach
drinks:
- water
- tea
```

This example shows the practical division of labor: `for...in` identifies which category keys exist, and `for...of` processes the items inside each category.

## 10. Key Points

- `for...of` loops over values from an iterable.
- `for...in` loops over enumerable property names.
- Use `for...of` for arrays, strings, sets, and maps when you want values.
- Use `for...in` for objects when you want keys, and filter with `Object.hasOwn()` if needed.
- Do not use `for...in` as a default array loop.
- Do not use `for...of` on plain objects unless you convert them first.

## 11. Practice Exercise

Try this small exercise to make the difference stick.

- Create an array of three city names and print each city with `for...of`.
- Create an object with three properties and print each key with `for...in`.
- Then print each object value by combining `for...in` with bracket notation.

**Expected output:** You should see each city name on its own line, followed by each object key and its corresponding value.

**Hint:** Remember that `for...of` gives values directly, while `for...in` gives keys that you can use to access values.

**Solution:**

```javascript
const cities = ["Paris", "Tokyo", "Lima"];
const person = {
  firstName: "Sam",
  lastName: "Lee",
  age: 29
};

for (const city of cities) {
  console.log(city);
}

for (const key in person) {
  if (Object.hasOwn(person, key)) {
    console.log(key + ":", person[key]);
  }
}
```

Output (tested with Node 24.21.0):

```text
Paris
Tokyo
Lima
firstName: Sam
lastName: Lee
age: 29
```

This solution works because each loop matches the structure it is meant to handle.

## 12. Final Summary

`for...of` and `for...in` are easy to confuse, but they answer different questions. `for...of` asks, “What are the values in this iterable?” while `for...in` asks, “What enumerable keys does this object have?”

For most array and string work, reach for `for...of`. For object-key inspection, use `for...in` carefully and remember to guard against inherited properties when necessary.

If you want to go further, next learn `Object.keys()`, `Object.entries()`, and how iterators make `for...of` possible.
