JavaScript for in Loop: Complete Guide
The for...in loop iterates over the enumerable property keys of an object. Learn when to use it, when to avoid it, and how it differs from for...of and Object.keys().
The for...in loop iterates over the enumerable property keys of an object. It is the oldest dedicated tool for walking through object properties and has been part of JavaScript since the beginning.
Unlike for...of, which gives you values, for...in gives you keys. This makes it the right loop for inspecting or processing the properties of a plain object.
Basic for...in Syntax
for (const key in object) {
// use key to access object[key]
}Each iteration assigns the next enumerable property name (as a string) to the loop variable. You then use bracket notation to access the corresponding value.
const user = {
name: "Alice",
age: 30,
city: "Seattle",
};
for (const key in user) {
console.log(`${key}: ${user[key]}`);
}Output (order may vary):
name: Alice
age: 30
city: SeattleEach key is a string. The loop variable key holds "name", then "age", then "city". Bracket notation user[key] retrieves the value for each key.
The Prototype Chain Problem
for...in does not stop at the object's own properties. It walks up the prototype chain and includes inherited enumerable properties:
const parent = { inherited: "from parent" };
const child = Object.create(parent);
child.own = "from child";
for (const key in child) {
console.log(key);
}
// Prints: own, inheritedThe inherited property comes from the parent object, not from child itself. In most cases you only want the object's own properties.
Filtering with hasOwnProperty()
Use hasOwnProperty() to include only the object's direct properties:
for (const key in child) {
if (Object.hasOwn(child, key)) {
console.log(`${key}: ${child[key]}`);
}
}
// Prints only: own: from childObject.hasOwn(obj, key) is the modern replacement for obj.hasOwnProperty(key). It returns true only for properties that belong directly to the object, not to any prototype.
The diagram shows why inherited properties appear: after exhausting the object's own keys, for...in checks the prototype, then the prototype's prototype, and so on. Without hasOwnProperty(), properties from every level of the chain enter your loop.
for...in vs Object.keys()
Object.keys() returns an array of an object's own enumerable property names. It is often a cleaner choice:
const car = { make: "Toyota", model: "Corolla", year: 2024 };
// for...in with hasOwnProperty
for (const key in car) {
if (Object.hasOwn(car, key)) {
console.log(key, car[key]);
}
}
// Object.keys: simpler, no prototype worries
for (const key of Object.keys(car)) {
console.log(key, car[key]);
}Both produce the same output for plain objects, but Object.keys() with for...of is shorter and cannot accidentally include inherited properties. Modern ECMAScript defines for...in traversal order (integer keys in ascending order, then string keys in creation order), and Object.keys() follows the same order.
Why Not Use for...in on Arrays
Arrays are objects, so for...in technically works on them. But it iterates over all enumerable properties, not just numeric indices:
const arr = ["a", "b", "c"];
arr.custom = "extra";
for (const key in arr) {
console.log(key, arr[key]);
}Output:
0 a
1 b
2 c
custom extraThe custom property "extra" is included alongside the numeric indices. If the Array prototype has been extended (rare in modern code, but possible with polyfills), those additions also appear.
// RIGHT: use for...of for array values
for (const value of arr) {
console.log(value); // a, b, c
}
// RIGHT: use classic for for array indices
for (let i = 0; i < arr.length; i++) {
console.log(i, arr[i]); // 0 a, 1 b, 2 c
}When for...in Is the Right Tool
Despite its caveats, for...in has valid use cases:
| Use Case | Why for...in |
|---|---|
| Quick debugging | Dump all keys including inherited ones to inspect an object |
| Legacy codebases | Working with pre-ES5 code that may not have Object.keys |
| Unknown prototype shape | When you genuinely need to see inherited properties |
| Property existence check | Combined with hasOwnProperty for a quick key scan |
For most modern code, Object.keys() combined with for...of is the safer default. For a full guide on object iteration, see looping through objects in JavaScript.
for...in vs for...of Side by Side
for...in | for...of | |
|---|---|---|
| Iterates over | Property keys (names) | Property values |
| Works on objects | Yes | No (not iterable) |
| Works on arrays | Yes, but not recommended | Yes |
| Includes prototype | Yes | N/A (iterables only) |
| Order guarantee | Yes (modern ES) | Yes (iteration protocol) |
| Introduced | ES1 | ES6 |
const colors = ["red", "green", "blue"];
// for...in: gives indices as strings
for (const index in colors) {
console.log(typeof index, index); // string 0, string 1, string 2
}
// for...of: gives values directly
for (const color of colors) {
console.log(color); // red, green, blue
}The difference is fundamental: for...in answers "what are the keys?" and for...of answers "what are the values?" For arrays, you almost always want the values. For objects, you usually want the keys to look up the values.
For more on array iteration and when to pick each loop type, see the guide comparing for, for...of, and forEach and the for...of loop guide.
Rune AI
Key Insights
- for...in iterates over enumerable property keys of an object.
- It walks the prototype chain, so inherited properties are included.
- Use hasOwnProperty() to filter out inherited properties.
- Do not use for...in on arrays; use for...of or a classic for loop.
- Object.keys() is often a cleaner alternative for own properties only.
- Modern ECMAScript defines traversal order (integer keys first, then string keys in creation order).
Frequently Asked Questions
What is the difference between for...in and for...of?
Does for...in iterate over inherited properties?
Should I use for...in on arrays?
Conclusion
The for...in loop is the built-in tool for iterating over object property keys. It is simple and works on any object, but it comes with two important caveats: it includes inherited properties from the prototype chain, and its traversal order -- while well-defined in modern ECMAScript (integer keys ascending, then string keys in creation order) -- is not always what you expect. When you need only own properties or a more predictable iteration, Object.keys() or Object.entries() is a safer choice.
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.