for...in vs for...of

Easy

JavaScript has two iteration statements that look similar but serve different purposes: for...in iterates over enumerable property keys (including inherited ones), while for...of iterates over iterable values (arrays, strings, maps, sets). Confusing them is a common source of bugs, especially when using for...in on arrays.

Interactive Visualization

for...in vs for...of

Step 1: Setup
const obj = { a: 1, b: 2 };
const arr = [10, 20, 30];
Output
No output yet
1 / 5

Key Points

  • for...in iterates over enumerable property keys (strings), including inherited ones
  • for...of iterates over iterable values (arrays, strings, maps, sets)
  • for...in on arrays gives string indices, not values — avoid this
  • for...in includes inherited properties — use hasOwnProperty to guard
  • Plain objects are NOT iterable — for...of throws on them
  • Use Object.keys/values/entries to iterate objects with for...of

Code Examples

for...in — Iterates Keys

const user = { name: "Alice", age: 30, role: "admin" };

for (const key in user) {
  console.log(key, user[key]);
}
// "name" "Alice"
// "age" 30
// "role" "admin"

for...in iterates over all enumerable property names (keys) of an object.

for...of — Iterates Values

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

for (const fruit of fruits) {
  console.log(fruit);
}
// "apple", "banana", "cherry"

// Works with strings too
for (const char of "hello") {
  console.log(char); // "h", "e", "l", "l", "o"
}

// Works with Map
const map = new Map([["a", 1], ["b", 2]]);
for (const [key, value] of map) {
  console.log(key, value);
}

for...of iterates over values of any iterable: arrays, strings, Maps, Sets.

Why NOT to Use for...in on Arrays

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

// for...in on arrays — BAD!
for (const key in arr) {
  console.log(key);        // "0", "1", "2" (strings!)
  console.log(typeof key); // "string" (not number!)
}

// Worse: inherited properties leak in
Array.prototype.customMethod = function() {};
for (const key in arr) {
  console.log(key); // "0", "1", "2", "customMethod" (!)
}
delete Array.prototype.customMethod;

// for...of on arrays — GOOD!
for (const value of arr) {
  console.log(value); // "a", "b", "c"
}

for...in gives string indices and includes inherited properties. Always use for...of for arrays.

Object Iteration with Object.entries

function Animal(name) { this.name = name; }
Animal.prototype.type = "animal";

const dog = new Animal("Rex");
dog.breed = "Lab";

// for...in includes inherited
for (const key in dog) {
  console.log(key); // "name", "breed", "type" (inherited!)
}

// Modern alternative: Object.entries + for...of
for (const [key, value] of Object.entries(dog)) {
  console.log(key, value); // "name" "Rex", "breed" "Lab"
}

Use Object.keys/values/entries for a clean approach that skips inherited properties.

Common Mistakes

  • Using for...in on arrays (gives string indices and includes inherited properties)
  • Using for...of on plain objects (throws TypeError — objects are not iterable)
  • Forgetting that for...in keys are always strings, even for arrays
  • Not guarding for...in with hasOwnProperty when inheritance is possible

Interview Tips

  • Clearly explain: for...in = keys, for...of = values
  • Know why for...in is dangerous on arrays (string keys, inherited props)
  • Show how Object.entries() + for...of replaces for...in for objects
  • Mention that for...of requires the Symbol.iterator protocol

Related Concepts