Historical Context & Motivation
JavaScript was created in 1995 as a simple scripting language for web browsers, but it quickly grew into something much more powerful. From the very beginning, objects were a core part of the language — they let developers store data as key-value pairs, much like a dictionary maps words to definitions. However, for many years, the only built-in way to loop through an object's properties was the for...in loop, which had some confusing quirks. As JavaScript matured, the language designers introduced cleaner, more predictable methods for iterating over objects.
The central problem is straightforward: arrays in JavaScript are easy to loop through with for loops, .forEach(), or for...of, but objects are not arrays. So how do you systematically visit every property in an object? The answer lies in converting object properties into arrays that you can then iterate with familiar array methods.
Core Principles & Definitions
Before diving into code, let's clarify the key ideas behind iterating objects. JavaScript objects store data in key-value pairs, where each key (also called a property name) is a string that maps to a corresponding value. The three static methods — Object.keys(), Object.values(), and Object.entries() — each extract a different piece of that key-value relationship and return it as an array.
Object.keys()
["name", "age", "grade"]Object.values()
["Alice", 16, "11th"]Object.entries()
[["name", "Alice"], ["age", 16]]Own vs. Inherited Properties
Object.keys() gives you a list of all the locker numbers. Object.values() gives you everything inside the lockers. Object.entries() gives you each locker number paired with its contents.Visual Explanation
The following diagram shows how a single JavaScript object is transformed into three different array outputs by each of the static methods. Notice how each method extracts a different slice of the same underlying data.
student contains three key-value pairs. The three arrows show how each static method extracts different information: keys only (cyan), values only (pink), or paired entries (amber).The key insight from this diagram is that all three methods convert the object into a regular array. Once you have an array, you can use any array iteration method you already know — for...of, .forEach(), .map(), and more. This "convert then iterate" strategy is the foundation of object iteration in modern JavaScript.
How Each Method Works
Object.keys() — Get Property Names
Object.keys(obj) accepts an object and returns an array of strings. Each string is one of the object's own enumerable property names. The order of keys in the returned array matches the order in which properties were added to the object (with integer-like keys sorted first).
string[] — an array of property name strings.Object.values() — Get Property Values
Object.values(obj) works the same way, but instead of returning the property names it returns the corresponding values. Values can be of any type — strings, numbers, booleans, other objects, or even functions.
any[] — an array of the property values in the same order as Object.keys().Object.entries() — Get Key-Value Pairs
Object.entries(obj) combines both pieces: it returns an array where each element is itself a two-element array — [key, value]. This is especially powerful when combined with destructuring in a for...of loop, which lets you unpack the key and value into separate variables in one line.
[key, value] use array destructuring to assign the first element (the key) and the second element (the value) to separate variables automatically.Common Iteration Patterns
Now that you know the three methods, let's look at the most common patterns developers use to loop through objects. The diagram below shows each method paired with the iteration technique that works best with it.
Object.keys() with .forEach(). Pattern 2 uses Object.entries() with for...of and destructuring. Pattern 3 uses Object.entries() with .map() to transform data.const [key, value] inside a for...of loop, the square brackets are performing array destructuring. Each entry from Object.entries() is a two-element array like ["name", "Alice"], and destructuring automatically assigns the first element to key and the second to value.Worked Example
Let's walk through a realistic scenario. Imagine you have an object representing a student's test scores, and you want to calculate their average and print each subject with its score.
const scores = { math: 92, english: 88, science: 95, history: 78 };Object.values() to get an array of just the numbers: const vals = Object.values(scores); // [92, 88, 95, 78][92, 88, 95, 78].reduce() to add all scores together: const total = vals.reduce((sum, score) => sum + score, 0); // 353Object.keys(scores).length: const avg = total / Object.keys(scores).length; // 88.25Object.entries() with a for...of loop to print each subject alongside its score: for (const [subject, score] of Object.entries(scores)) { console.log(`${subject}: ${score}`); } This outputs: math: 92, english: 88, science: 95, history: 78.Comparing Object Iteration Methods
You now know three static methods for iterating objects, but JavaScript also has the older for...in loop. Understanding how they compare will help you choose the right tool for each situation.
| Feature | for...in | Object.keys() | Object.entries() |
|---|---|---|---|
| Returns | Keys (one at a time in loop) | Array of key strings | Array of [key, value] pairs |
| Includes inherited properties? | Yes | No (own only) | No (own only) |
| Works with array methods? | No | Yes (.map, .filter, etc.) | Yes (.map, .filter, etc.) |
| Supports destructuring? | No | Not directly | Yes — [key, value] |
| Best for | Legacy code, prototype inspection | When you only need keys | When you need both keys and values |
for...in because they skip inherited properties and return real arrays you can chain with .map(), .filter(), and other array methods. Think of for...in like an older phone — it still works, but the newer models have better features and fewer bugs.Connection to Advanced Concepts
The methods you learned here are building blocks for more advanced JavaScript patterns. As you progress, you'll encounter situations where these techniques combine with other tools to solve complex problems.
| What You Learned Today | Where It Leads |
|---|---|
Object.entries() to convert object → array | Object.fromEntries() converts array → object (the reverse) |
| Iterating flat objects with simple values | Recursively iterating nested objects (objects inside objects) |
Using .map() and .filter() on entries | Transforming API response data in real-world web apps |
| Own enumerable properties only | Symbols, non-enumerable properties, and Reflect.ownKeys() |
One particularly useful advanced pattern is using Object.entries() combined with .filter() and Object.fromEntries() to create a new object containing only the properties that pass a test. This is essentially "filtering an object," which JavaScript doesn't support natively but becomes easy with these tools.
Practice Problems
Object.keys() and Object.entries() return. Why would you choose one over the other?const pet = { species: "dog", name: "Max", age: 5 };, what does Object.keys(pet) return? What does Object.values(pet) return?Object.entries() and a for...of loop that takes the object const prices = { apple: 1.20, banana: 0.50, cherry: 3.00 }; and logs each fruit with a 10% price increase in the format "apple: $1.32".const attendance = { Alice: 18, Bob: 12, Carol: 20, Dave: 9 }; where each value is the number of days attended out of 20. Using Object.entries() and array methods, write code that creates an array of names of students who attended fewer than 15 days.for...in with hasOwnProperty() checks, and (B) using Object.keys() with .forEach(). Under what circumstances might approach (A) still be useful? Discuss readability, safety, and potential edge cases.Lesson Summary
JavaScript objects store data as key-value pairs, but unlike arrays, they aren't directly iterable. The solution is to convert them into arrays using three static methods: Object.keys() returns an array of property name strings, Object.values() returns an array of property values, and Object.entries() returns an array of [key, value] pairs. All three methods return only the object's own enumerable properties, avoiding the inherited-property pitfalls of the older for...in loop.
Once you have an array, you can use any standard array iteration method — for...of, .forEach(), .map(), or .filter(). The most powerful combination is Object.entries() with destructuring in a for...of loop, which gives you clean access to both keys and values in every iteration.