The for...in
statement iterates over all enumerable string properties of an object (ignoring properties keyed by symbols), including inherited enumerable properties.
The for...in
statement iterates over all enumerable string properties of an object (ignoring properties keyed by symbols), including inherited enumerable properties.
for (variable in object) statement
variable
Receives a string property name on each iteration. May be either a declaration with const
, let
, or var
, or an assignment target (e.g. a previously declared variable, an object property, or a destructuring assignment pattern). Variables declared with var
are not local to the loop, i.e. they are in the same scope the for...in
loop is in.
object
Object whose non-symbol enumerable properties are iterated over.
statement
A statement to be executed on every iteration. May reference variable
. You can use a block statement to execute multiple statements.
The loop will iterate over all enumerable properties of the object itself and those the object inherits from its prototype chain (properties of nearer prototypes take precedence over those of prototypes further away from the object in its prototype chain).
A for...in
loop only iterates over enumerable, non-symbol properties. Objects created from built–in constructors like Array
and Object
have inherited non–enumerable properties from Array.prototype
and Object.prototype
, such as Array
's indexOf()
method or Object
's toString()
method, which will not be visited in the for...in
loop.
The traversal order, as of modern ECMAScript specification, is well-defined and consistent across implementations. Within each component of the prototype chain, all non-negative integer keys (those that can be array indices) will be traversed first in ascending order by value, then other string keys in ascending chronological order of property creation.
The variable
part of for...in
accepts anything that can come before the =
operator. You can use const
to declare the variable as long as it's not reassigned within the loop body (it can change between iterations, because those are two separate variables). Otherwise, you can use let
. You can use destructuring to assign multiple local variables, or use a property accessor like for (x.y in iterable)
to assign the value to an object property.
A legacy syntax allows var
declarations of the loop variable to have an initializer. This throws a syntax error in strict mode and is ignored in non–strict mode.
for...in
visits property keys in the following fashion:
Object.getOwnPropertyNames()
.This means:
In general, it is best not to add, modify, or remove properties from the object during iteration, other than the property currently being visited. The spec explicitly allows the implementation to not follow the algorithm above in one of the following cases:
In these cases, implementations may behave differently from what you may expect, or even from each other.
Array indexes are just enumerable properties with integer names and are otherwise identical to general object properties. The for...in
loop will traverse all integer keys before traversing other keys, and in strictly increasing order, making the behavior of for...in
close to normal array iteration. However, the for...in
loop will return all enumerable properties, including those with non–integer names and those that are inherited. Unlike for...of
, for...in
uses property enumeration instead of the array's iterator. In sparse arrays, for...of
will visit the empty slots, but for...in
will not.
It is better to use a for
loop with a numeric index, Array.prototype.forEach()
, or the for...of
loop, because they will return the index as a number instead of a string, and also avoid non-index properties.
If you only want to consider properties attached to the object itself, and not its prototypes, you can use one of the following techniques:
Object.keys
will return a list of enumerable own string properties, while Object.getOwnPropertyNames
will also contain non-enumerable ones.
Many JavaScript style guides and linters recommend against the use of for...in
, because it iterates over the entire prototype chain which is rarely what one wants, and may be a confusion with the more widely-used for...of
loop. for...in
is most practically used for debugging purposes, being an easy way to check the properties of an object (by outputting to the console or otherwise). In situations where objects are used as ad hoc key-value pairs, for...in
allows you check if any of those keys hold a particular value.
The for...in
loop below iterates over all of the object's enumerable, non-symbol properties and logs a string of the property names and their values.
const obj = { a: 1, b: 2, c: 3 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); } // Logs: // "obj.a = 1" // "obj.b = 2" // "obj.c = 3"
The following function illustrates the use of Object.hasOwn()
: the inherited properties are not displayed.
const triangle = { a: 1, b: 2, c: 3 }; function ColoredTriangle() { this.color = "red"; } ColoredTriangle.prototype = triangle; const obj = new ColoredTriangle(); for (const prop in obj) { if (Object.hasOwn(obj, prop)) { console.log(`obj.${prop} = ${obj[prop]}`); } } // Logs: // "obj.color = red"
Warning: You should not write code like this yourself. It is only included here to illustrate the behavior of for...in
in some corner cases.
Properties added to the current object during iteration are never visited:
const obj = { a: 1, b: 2 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); obj.c = 3; } // Logs: // obj.a = 1 // obj.b = 2
Shadowed properties are only visited once:
const proto = { a: 1 }; const obj = { __proto__: proto, a: 2 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); } // Logs: // obj.a = 2 Object.defineProperty(obj, "a", { enumerable: false }); for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); } // Logs nothing, because the first "a" property visited is non-enumerable.
In addition, consider the following cases, where the behavior is unspecified, and implementations tend to diverge from the specified algorithm:
Changing the prototype during iteration:
const obj = { a: 1, b: 2 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); Object.setPrototypeOf(obj, { c: 3 }); }
Deleting a property during iteration:
const obj = { a: 1, b: 2, c: 3 }; // Deleting a property before it is visited for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); delete obj.c; } const obj2 = { a: 1, b: 2, c: 3 }; // Deleting a property after it is visited for (const prop in obj2) { console.log(`obj2.${prop} = ${obj2[prop]}`); delete obj2.a; }
Enumerable properties added to the prototype during iteration:
const proto = {}; const obj = { __proto__: proto, a: 1, b: 2 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); proto.c = 3; }
Changing the enumerability of a property during iteration:
const obj = { a: 1, b: 2, c: 3 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); Object.defineProperty(obj, "c", { enumerable: false }); }
Desktop | Mobile | Server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | Deno | Node.js | ||
for...in |
1 | 12 | 1 | 2 | 1 | 18 | 4 | 10.1 | 1 | 1.0 | 4.4 | 1.0 | 0.10.0 |
© 2005–2023 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in