Looping Through Objects in JavaScript: Complete Guide
Plain objects are not iterable with for...of, but JavaScript gives you three clean ways to loop through them. Learn Object.keys(), Object.values(), Object.entries(), and when for...in is the right choice.
Unlike arrays, plain objects in JavaScript are not iterable. You cannot use for...of on an object directly. But JavaScript gives you several built-in methods that turn an object into something you can loop over.
The three main tools are Object.keys(), Object.values(), and Object.entries(). Each converts an object's properties into an array, which you can then iterate with for...of or any array method.
Object.keys(): Loop Over Property Names
Object.keys() returns an array of the object's own enumerable property names:
const book = {
title: "JavaScript: The Good Parts",
author: "Douglas Crockford",
year: 2008,
};
for (const key of Object.keys(book)) {
console.log(`${key}: ${book[key]}`);
}Output:
title: JavaScript: The Good Parts
author: Douglas Crockford
year: 2008Object.keys() only returns the object's own properties, not inherited ones. This makes it safer than for...in for most use cases. The returned array works with any array method, not just loops:
const keys = Object.keys(book);
console.log(keys); // ["title", "author", "year"]
console.log(keys.length); // 3
console.log(keys.includes("author")); // trueObject.values(): Loop Over Property Values
Object.values() returns an array of the object's own enumerable property values:
const scores = {
Alice: 92,
Bob: 85,
Carol: 78,
};
for (const score of Object.values(scores)) {
console.log(score);
}
// Prints: 92, 85, 78This is the cleanest option when you only care about the values and do not need the keys. Combined with array methods, it is powerful:
const allScores = Object.values(scores);
const average = allScores.reduce((sum, s) => sum + s, 0) / allScores.length;
console.log(average); // 85Object.entries(): Loop Over Key-Value Pairs
Object.entries() returns an array of [key, value] pairs. This is the most versatile option because you get both key and value in one call:
const product = {
name: "Laptop",
price: 999,
inStock: true,
};
for (const [key, value] of Object.entries(product)) {
console.log(`${key} = ${value} (${typeof value})`);
}Output:
name = Laptop (string)
price = 999 (number)
inStock = true (boolean)Array destructuring in the loop header unpacks each pair into key and value. This pattern is the go-to for most object iteration in modern JavaScript because it is concise and gives you everything you need.
The Three Methods Compared
const pet = { name: "Rex", species: "Dog", age: 4 };| Method | Returns | Example Output |
|---|---|---|
Object.keys(pet) | Array of keys | ["name", "species", "age"] |
Object.values(pet) | Array of values | ["Rex", "Dog", 4] |
Object.entries(pet) | Array of [key, value] | [["name","Rex"], ["species","Dog"], ["age",4]] |
All three methods return arrays, which means you can use for...of, forEach, map, filter, reduce, or any array operation on the result.
for...in: The Lower-Level Alternative
for...in also iterates over object keys, but with one key difference: it includes inherited enumerable properties from the prototype chain:
const base = { shared: true };
const derived = Object.create(base);
derived.own = "value";
// for...in sees both own and inherited
for (const key in derived) {
console.log(key); // own, shared
}
// Object.keys only sees own properties
console.log(Object.keys(derived)); // ["own"]For most everyday object iteration, Object.keys() with for...of is safer because it avoids prototype surprises. Use for...in when you genuinely need to see inherited properties or when debugging. For a full comparison, see the for...in guide.
Practical Patterns
Transforming an object
const prices = { apple: 1.0, banana: 0.5, cherry: 2.0 };
const discounted = {};
for (const [fruit, price] of Object.entries(prices)) {
discounted[fruit] = price * 0.8;
}
console.log(discounted);
// { apple: 0.8, banana: 0.4, cherry: 1.6 }Filtering properties
const user = { id: 1, name: "Alice", password: "secret", token: "abc123" };
const publicFields = {};
for (const [key, value] of Object.entries(user)) {
if (key !== "password" && key !== "token") {
publicFields[key] = value;
}
}
console.log(publicFields); // { id: 1, name: "Alice" }Building a query string
const params = { search: "laptop", page: 1, sort: "price" };
const query = Object.entries(params)
.map(([key, value]) => `${key}=${value}`)
.join("&");
console.log(query); // "search=laptop&page=1&sort=price"Counting occurrences
const words = ["apple", "banana", "apple", "cherry", "banana", "apple"];
const counts = {};
for (const word of words) {
counts[word] = (counts[word] || 0) + 1;
}
for (const [word, count] of Object.entries(counts)) {
console.log(`${word}: ${count}`);
}
// apple: 3, banana: 2, cherry: 1Choosing the Right Tool
| Situation | Best Choice |
|---|---|
| Need both key and value | Object.entries() |
| Need only keys | Object.keys() |
| Need only values | Object.values() |
| Need inherited properties | for...in |
| Need array methods (map, filter) | Object.entries() + array method |
| Quick debug dump | console.log(obj) or Object.entries() |
For array iteration, see the array looping guide and the for...of guide. For choosing between for, for...of, and forEach across data types, see the loop comparison guide.
Rune AI
Key Insights
- Plain objects are not iterable; use Object.keys/values/entries or for...in.
- Object.keys(obj) returns an array of the object's own property names.
- Object.values(obj) returns an array of the object's own property values.
- Object.entries(obj) returns an array of [key, value] pairs.
- for...in includes inherited properties; use hasOwnProperty() to filter them.
Frequently Asked Questions
Why can't I use for...of on a plain object?
Does Object.keys() guarantee the same order as for...in?
Which method should I use as a default for object iteration?
Conclusion
Plain objects need a different approach than arrays for iteration. Object.keys(), Object.values(), and Object.entries() convert an object into an array you can loop over with for...of, giving you clean syntax and avoiding prototype chain surprises. for...in is the lower-level alternative when you need to include inherited properties or work in older environments.
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.