for...in vs for...of
EasyJavaScript 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