Looping Over Objects

JavaScript ECMAScript 2024 · ✓ verified by execution on 2026-08-14

When you work with arrays, you have straightforward loops like for...of or .forEach(). But when you try to loop over a plain JavaScript object using for...of, you get a surprise.

Predict the output javascript

Read the code. What exactly will it print? Commit to an answer before you look.

const plainObj = { a: 1, b: 2 };
try {
  for (const val of plainObj) {
    console.log(val);
  }
} catch (e) {
  console.log(e.name + ": plainObj is not iterable");
}
Output
TypeError: plainObj is not iterable

Plain objects are not iterable. You cannot loop over them directly with for...of. To loop through an object in JavaScript, you must first convert it into an array of its keys, its values, or both.

The Object Iteration Methods

JavaScript provides three static methods on the Object constructor to extract arrays from an object.

Let’s see them in action.

javascript
const user = { name: 'Alice', age: 25 };

console.log(Object.keys(user));
// Outputs: [ 'name', 'age' ]

console.log(Object.values(user));
// Outputs: [ 'Alice', 25 ]
Output
[ 'name', 'age' ]
[ 'Alice', 25 ]

Notice that these methods return standard arrays. Because they are arrays, you can now use a for...of loop!

javascript
const scores = { math: 90, english: 85 };
const keys = Object.keys(scores);

for (const key of keys) {
  console.log(key, scores[key]);
}
Output
math 90
english 85

Object.entries() and Destructuring

If you need both the keys and the values, Object.entries() is the most powerful tool. It transforms your object into a 2D array of [key, value] pairs.

Object make: 'Ford' model: 'Mustang' Object.entries() Array of Arrays [ 'make', 'Ford' ] [ 'model', 'Mustang' ]
Object.entries() converts an object into an array of [key, value] pairs, which is what makes an object iterable by the ordinary array methods.

When combined with array destructuring in a for...of loop, Object.entries() creates incredibly clean iteration logic.

javascript
const inventory = { apples: 5, oranges: 10 };

for (const [key, value] of Object.entries(inventory)) {
  console.log(`${key}: ${value}`);
}
Output
apples: 5
oranges: 10

The for…in Loop

JavaScript also has a specialized loop called for...in. It is designed specifically for iterating over an object’s keys.

javascript · visualize
const settings = { theme: 'dark', notifications: true };

for (const key in settings) {
  console.log(key, settings[key]);
}

While for...in looks simpler than Object.keys(), there is a critical difference: for...in iterates over all enumerable string properties of an object, including inherited properties from the prototype chain. Object.keys() only returns the object’s own properties.

Because of this risk of accidentally looping over inherited methods or properties, modern JavaScript development heavily prefers Object.keys(), Object.values(), and Object.entries().

Iteration Order

A common misconception is that object properties are completely unordered. In modern JavaScript, iteration methods follow a specific, guaranteed order:

  1. Integer keys (like '1', '2') are sorted in ascending numeric order.
  2. String keys are returned in the chronological order they were inserted.
  3. Symbol keys (which are ignored by Object.keys() and for...in) are returned last in insertion order.

Check yourself

What does `Object.values({ a: 1, b: 2 })` return?

Reveal answer

[ 1, 2 ] — Object.values() returns a standard Array containing only the object's values.

Why is `Object.keys()` generally preferred over `for...in` for plain objects?

Reveal answer

`Object.keys()` only returns the object's own properties, avoiding inherited ones. — `for...in` iterates over inherited enumerable properties on the prototype chain, which can cause unexpected bugs if the prototype has been modified.

Are JavaScript object properties completely unordered?

Reveal answer

No, modern JavaScript guarantees a specific order: integer keys first, then string keys by insertion. — Modern JavaScript engines follow a strict order: integer keys in ascending numeric order, followed by string keys in insertion order.

Challenges

🐞 Bug Hunt +25 XP

A developer tried to count the properties in `settings` but it prints `undefined` instead of `3`. Fix their code.

This code runs. It just does the wrong thing. Read it, find the defect, fix it — the tests below decide when you are right.

javascript
  • Test 1 — expects "3\n"
Need a hint? (−25% XP)

Plain objects don't have a `.length` property. You need to extract an array of keys using `Object.keys()` first.

Show solution (0 XP)
const settings = { volume: 80, brightness: 50, wifi: true };
console.log(Object.keys(settings).length);

Challenge 2 +25 XP

Use `for...of` and `Object.entries()` to iterate over the `prices` object and print each item exactly like "apple costs $2".

javascript
  • Test 1 — expects "apple costs $2\nbanana costs $1\ncherry costs $3\n"
Need a hint? (−25% XP)

Use array destructuring like `const [item, price]` inside the `for...of` loop.

Show solution (0 XP)
const prices = { apple: 2, banana: 1, cherry: 3 };
for (const [item, price] of Object.entries(prices)) {
  console.log(`${item} costs $${price}`);
}