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().

6 min read

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

javascriptjavascript
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.

javascriptjavascript
const user = {
  name: "Alice",
  age: 30,
  city: "Seattle",
};
 
for (const key in user) {
  console.log(`${key}: ${user[key]}`);
}

Output (order may vary):

texttext
name: Alice
age: 30
city: Seattle

Each 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:

javascriptjavascript
const parent = { inherited: "from parent" };
const child = Object.create(parent);
child.own = "from child";
 
for (const key in child) {
  console.log(key);
}
// Prints: own, inherited

The 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:

javascriptjavascript
for (const key in child) {
  if (Object.hasOwn(child, key)) {
    console.log(`${key}: ${child[key]}`);
  }
}
// Prints only: own: from child

Object.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.

for...in prototype chain traversal

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:

javascriptjavascript
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:

javascriptjavascript
const arr = ["a", "b", "c"];
arr.custom = "extra";
 
for (const key in arr) {
  console.log(key, arr[key]);
}

Output:

texttext
0 a
1 b
2 c
custom extra

The 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.

javascriptjavascript
// 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 CaseWhy for...in
Quick debuggingDump all keys including inherited ones to inspect an object
Legacy codebasesWorking with pre-ES5 code that may not have Object.keys
Unknown prototype shapeWhen you genuinely need to see inherited properties
Property existence checkCombined 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...infor...of
Iterates overProperty keys (names)Property values
Works on objectsYesNo (not iterable)
Works on arraysYes, but not recommendedYes
Includes prototypeYesN/A (iterables only)
Order guaranteeYes (modern ES)Yes (iteration protocol)
IntroducedES1ES6
javascriptjavascript
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

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).
RunePowered by Rune AI

Frequently Asked Questions

What is the difference between for...in and for...of?

for...in iterates over property keys (names). for...of iterates over values. Use for...in for plain objects to get property names. Use for...of for arrays, strings, Maps, and Sets to get values.

Does for...in iterate over inherited properties?

Yes. for...in walks the prototype chain and includes enumerable properties from prototypes. Use hasOwnProperty() inside the loop or prefer Object.keys() to avoid inherited properties.

Should I use for...in on arrays?

Generally no. for...in iterates over all enumerable properties, not just indices. If the array has custom properties or the prototype has been extended, for...in can include unexpected keys. Use for...of or a classic for loop for 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.