For...in loop in JavaScript

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

  1. Works on objects (not ideal for arrays): It loops keys, not values. For arrays, use for...of or .forEach().

  2. Includes inherited keys: By default, it also iterates keys that come from the object’s prototype chain.

  3. Ignores Symbol keys: Only string keys are visited.

  4. 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, classic for, or .forEach().

  • When you need values directlyfor...of on Object.values(obj) or Object.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; use for...of, .forEach(), or a classic for.

  • Symbol keys and non-enumerable properties are skipped.

  • Don’t rely on property order.

No comments:

Post a Comment

What is slice() in JavaScript

What is slice() ? slice() is a method used to copy a portion of an array or string without changing the original . Think of it like cut...