Suggest an editImprove this articleRefine the answer for “For...in vs for...of in JavaScript”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`for...in`** iterates over enumerable property keys (as strings) of an object. **`for...of`** iterates over values from any iterable. ```javascript const obj = { a: 1 }; const arr = [1, 2]; for (const key in obj) { console.log(key); } // "a" (string key) for (const val of arr) { console.log(val); } // 1, 2 (values) ``` **Key rule:** use `for...in` for objects, `for...of` for arrays, strings, Maps, and Sets. Never use `for...in` on arrays - it yields string indices and includes prototype properties.Shown above the full answer for quick recall.Answer (EN)Image**`for...in` iterates over enumerable property keys (strings) of an object; `for...of` iterates over values from any iterable like arrays, strings, Maps, or Sets.** ## Theory ### TL;DR - `for...in` reads keys (like label slots on a mailbox); `for...of` reads values (the letters inside) - `for...in` always yields string keys; `for...of` yields actual values of any type - `for...in` traverses the prototype chain; `for...of` ignores it - Plain object? `for...in`. Array, string, Map, Set? `for...of` - `for...in` on arrays technically runs but causes real bugs ### Quick example ```javascript const obj = { a: 1, b: 2 }; const arr = [1, 2]; for (const key in obj) { console.log(key); // "a", "b" (string keys) } for (const val of arr) { console.log(val); // 1, 2 (actual values) } ``` `for...in` gives you keys as strings. `for...of` gives you values directly. That is the whole split. ### Key difference `for...in` was designed for objects. It walks all enumerable properties including those inherited through the prototype chain, and always yields string keys. `for...of` was introduced in ES2015 and works with anything that has a `[Symbol.iterator]` method. No prototype traversal, no string coercion. Just values in sequence. ### When to use - Inspecting object structure (a config object, `req.headers`): use `for...in` - Looping through array elements, characters in a string, or Map/Set entries: use `for...of` - Need both keys and values from an object: `for (const [k, v] of Object.entries(obj))` - Want to avoid prototype chain surprises: `Object.keys(obj)` with `for...of` is the safer path ### Comparison table | Aspect | for...in | for...of | |---|---|---| | Iterates over | Enumerable property keys (strings) | Values from iterables | | Works on | Objects (including arrays) | Arrays, strings, Maps, Sets, generators | | Prototype chain | Includes inherited properties | Ignored | | Array behavior | Indices as strings ("0", "1") | Direct elements, holes become `undefined` | | Typical use | Object key inspection | Collection traversal | ### How it works `for...in` calls the internal enumerate operation, walks own and prototype properties, and yields each key as a string. That is why you get `"0"` instead of `0` on arrays. `for...of` calls `[Symbol.iterator]()` on the target, then calls `.next()` in a loop, reading each `{value, done}` object until `done` is `true`. No prototype traversal. If the object has no `[Symbol.iterator]`, you get a `TypeError` immediately. ### Common mistakes **Using `for...in` on arrays** ```javascript const arr = ["a", "b"]; for (const i in arr) { console.log(i, typeof i); // "0" "string", "1" "string" } ``` Indices become strings, not numbers. Sparse arrays behave unpredictably, and if any library added a property to `Array.prototype`, that shows up in the loop too. Use `for...of` or a plain `for` loop. **Assuming `for...of` works on plain objects** ```javascript const obj = { a: 1, b: 2 }; for (const val of obj) { } // TypeError: obj is not iterable ``` Plain objects have no `[Symbol.iterator]`. Fix: `for (const val of Object.values(obj))`. **Prototype pollution with `for...in`** ```javascript const arr = ["a", "b"]; Array.prototype.foo = "polluted"; for (const key in arr) { console.log(key); // "0", "1", "foo" } ``` This happens more often than you would expect in older codebases. Add a `hasOwnProperty` check or avoid `for...in` on arrays entirely. **Modifying an object during the loop** ```javascript const obj = { a: 1, b: 2 }; for (const k in obj) { delete obj.b; // May skip "b" in V8 - behavior not guaranteed } ``` V8 snapshots keys before the loop starts. Deleting properties mid-iteration can cause skips. Collect keys first with `Object.keys()`. ### Real-world usage - Express: `for...in` on `req.headers` to log all incoming header names - React: `for...of` when building DOM lists or processing array props in custom loops - Node.js: `for...of` on `process.argv.slice(2)` to iterate CLI arguments - Lodash: `_.forIn` wraps `for...in` safely for object enumeration ### Follow-up questions **Q:** What does `for...in` produce on an array with holes? **A:** It skips holes entirely since there is no property at that index. `for...of` yields `undefined` for each hole. **Q:** How do you make a plain object work with `for...of`? **A:** Wrap it with `Object.values(obj)`, or add a custom `[Symbol.iterator]` generator method to the object. **Q:** Why does `for...in` return string keys on arrays? **A:** The spec coerces all property keys to strings. Arrays store elements as named properties, so index `0` becomes `"0"`. **Q:** Is iteration order guaranteed? **A:** `for...of` on arrays and strings follows insertion order. `for...in` order is not guaranteed by the spec, though V8 typically returns own keys first, then prototype keys. **Q:** (Senior) What happens in V8 when you delete a property during `for...in`? **A:** V8 builds a key snapshot before the loop starts. Deleting a property after that point does not reliably remove it from iteration. The behavior is unspecified by the spec, so do not depend on it. ## Examples ### Inspecting a config object ```javascript const settings = { theme: "dark", lang: "en", debug: true }; for (const key in settings) { console.log(`${key}: ${settings[key]}`); } // theme: dark // lang: en // debug: true ``` `for...in` is clean for plain objects when you need the keys. This pattern shows up in config validation, logging middleware, and anywhere you inspect an object without knowing its shape in advance. ### Building a list from an array ```javascript const todos = ["Buy milk", "Write code", "Sleep"]; const list = document.createElement("ul"); for (const todo of todos) { const item = document.createElement("li"); item.textContent = todo; list.appendChild(item); } // <ul><li>Buy milk</li><li>Write code</li><li>Sleep</li></ul> ``` `for...of` gives you elements directly. No index variable, no bracket access. This is the standard pattern for building DOM nodes or processing any ordered collection.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.