What is for...in
?
for...in
is a loop that goes over the enumerable property keys (names) of an object. Each turn of the loop gives you a key (a string). You can use that key to access the value with bracket notation.
Think of it as: “Give me every key in this object.”
Syntax
for (const key in someObject) {
// use key and someObject[key]
}
-
key
→ each property name (string) -
someObject[key]
→ the value for that key
Basic example (objects)
const user = { name: "Gagan", role: "Developer", active: true };
for (const key in user) {
console.log(key, "=>", user[key]);
}
// name => Gagan
// role => Developer
// active => true
Important behaviors to know
-
Works on objects (not ideal for arrays): It loops keys, not values. For arrays, use
for...of
or.forEach()
. -
Includes inherited keys: By default, it also iterates keys that come from the object’s prototype chain.
-
Ignores Symbol keys: Only string keys are visited.
-
Enumeration order: Don’t rely on the order. (Integer-like keys tend to come first, but avoid depending on it.)
Filtering out inherited keys (best practice)
Because for...in
also sees keys from prototypes, you’ll often add a check:
const user = Object.create({ fromProto: "hello" });
user.name = "Gagan";
user.role = "Developer";
for (const key in user) {
if (Object.prototype.hasOwnProperty.call(user, key)) {
console.log(key, user[key]); // prints only "name" and "role"
}
}
Shortcut in modern JS:
if (Object.hasOwn(user, key)) { ... }
When should you use for...in
?
-
When you want to iterate over all enumerable keys of a plain object, especially when you don’t need an array of keys first.
-
When you are okay handling (or filtering) inherited keys.
When should you avoid it?
-
Arrays: It loops indices as strings and can include extra/custom properties—use
for...of
, classicfor
, or.forEach()
. -
When you need values directly—
for...of
onObject.values(obj)
orObject.entries(obj)
is cleaner. -
When you want a guaranteed order—convert to arrays with
Object.keys/values/entries
.
Examples you’ll actually use
1) Loop an object and read values
const product = { id: 101, title: "Keyboard", price: 799 };
for (const key in product) {
if (Object.hasOwn(product, key)) {
console.log(`${key}: ${product[key]}`);
}
}
2) Build a new object while looping
const raw = { name: " gagan ", city: " jaipur" };
const cleaned = {};
for (const key in raw) {
if (Object.hasOwn(raw, key)) {
cleaned[key] = String(raw[key]).trim();
}
}
console.log(cleaned); // { name: "gagan", city: "jaipur" }
3) Count own properties
function countOwnProps(obj) {
let count = 0;
for (const key in obj) {
if (Object.hasOwn(obj, key)) count++;
}
return count;
}
console.log(countOwnProps({ a: 1, b: 2, c: 3 })); // 3
4) Beware prototypes: inherited keys appear
const proto = { shared: true };
const obj = Object.create(proto);
obj.own = 123;
for (const key in obj) {
console.log(key); // "own", then "shared" (inherited)
}
Filter with Object.hasOwn(obj, key)
if you only want own
.
5) Not recommended for arrays
const arr = ["apple", "banana"];
arr.extra = "x";
for (const i in arr) {
console.log(i, arr[i]);
}
// "0" "apple"
// "1" "banana"
// "extra" "x" <-- surprise!
Prefer:
for (const value of arr) console.log(value);
// apple
// banana
6) Compare: for...in
vs for...of
const obj = { a: 10, b: 20 };
const arr = [10, 20];
// for...in => keys (strings)
for (const k in obj) console.log(k); // "a", "b"
for (const k in arr) console.log(k); // "0", "1"
// for...of => values (iterables only)
for (const v of arr) console.log(v); // 10, 20
// for...of doesn't work directly on plain objects:
// for (const v of obj) {} // TypeError
// To use for...of with objects, convert with helpers:
for (const [k, v] of Object.entries(obj)) {
console.log(k, v); // "a" 10, "b" 20
}
7) Skipping non-enumerable and Symbol keys
const o = {};
Object.defineProperty(o, "hidden", { value: 1, enumerable: false });
o.visible = 2;
const s = Symbol("id");
o[s] = 3;
for (const k in o) {
console.log(k); // only "visible"
}
Handy patterns
Loop over keys (own only):
for (const key in obj) {
if (!Object.hasOwn(obj, key)) continue;
// use obj[key]
}
Safest, most readable alternative for many cases:
Object.entries(obj).forEach(([key, value]) => {
// use key, value
});
Quick cheat sheet
-
Use
for...in
to iterate keys of an object. -
Always guard with
Object.hasOwn(obj, key)
if you don’t want inherited keys. -
Don’t use
for...in
for arrays; usefor...of
,.forEach()
, or a classicfor
. -
Symbol keys and non-enumerable properties are skipped.
-
Don’t rely on property order.
No comments:
Post a Comment