SECTION 1
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.
1995 • JavaScript Created
1999 • ECMAScript 3 — for...in Loop
2011 • ES5 — Object.keys() Introduced
2017 • ES8 — Object.entries() & Object.values()
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.
SECTION 2
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
KEY TAKEAWAY
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.SECTION 3
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.
SECTION 4
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).
SYNTAX — OBJECT.KEYS
Returns: 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.
SYNTAX — OBJECT.VALUES
Returns: 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.
SYNTAX — OBJECT.ENTRIES WITH DESTRUCTURING
The square brackets [key, value] use array destructuring to assign the first element (the key) and the second element (the value) to separate variables automatically.
SECTION 5
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.Destructuring Tip
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.SECTION 6
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.
Calculate Average Test Score from an Object
- 1
Step 1 — Define the Object
We start with a scores object where each key is a subject name and each value is a numeric score:const scores = { math: 92, english: 88, science: 95, history: 78 };Object with 4 key-value pairs - 2
Step 2 — Extract the Values
Since we need the numeric scores to compute an average, we useObject.values()to get an array of just the numbers:const vals = Object.values(scores); // [92, 88, 95, 78][92, 88, 95, 78] - 3
Step 3 — Sum the Values
We can use.reduce()to add all scores together:const total = vals.reduce((sum, score) => sum + score, 0); // 353total = 353 - 4
Step 4 — Calculate the Average
Divide the total by the number of subjects. We can get the count fromObject.keys(scores).length:const avg = total / Object.keys(scores).length; // 88.25average = 88.25 - 5
Step 5 — Print Each Subject with Its Score
Now useObject.entries()with afor...ofloop 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.Each subject and score printed on its own line
SECTION 7
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 |
Comparison of object iteration approaches in JavaScript
KEY TAKEAWAY
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.SECTION 8
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() |
How today's concepts connect to advanced JavaScript
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.
SECTION 9
Practice Problems
Question 1: CONCEPTUAL
Object.keys() and Object.entries() return. Why would you choose one over the other?Show answer
Object.keys() returns an array of strings — just the property names (keys) of the object. Object.entries() returns an array of two-element arrays, where each inner array contains a key and its corresponding value. You would choose Object.keys() when you only need property names (for example, to count properties or check if a key exists). You would choose Object.entries() when you need both the key and the value together, especially since you can destructure each entry in a for...of loop for cleaner code.Question 2: BASIC CALCULATION
const pet = { species: "dog", name: "Max", age: 5 };, what does Object.keys(pet) return? What does Object.values(pet) return?Show answer
Object.keys(pet) returns ["species", "name", "age"] — an array of the three property name strings. Object.values(pet) returns ["dog", "Max", 5] — an array containing the values in the same order as the keys. Notice that values can be different types (strings and numbers mixed together).Question 3: INTERMEDIATE
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".Show answer
for (const [fruit, price] of Object.entries(prices)) { console.log(`${fruit}: $${(price * 1.10).toFixed(2)}`); } Here, [fruit, price] destructures each entry. We multiply the price by 1.10 to add 10% and use .toFixed(2) to format the number to two decimal places. The output would be: apple: $1.32, banana: $0.55, cherry: $3.30.Question 4: APPLIED
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.Show answer
.filter() and .map() on the entries array: const lowAttendance = Object.entries(attendance).filter(([name, days]) => days < 15).map(([name, days]) => name); First, .filter() keeps only entries where days is less than 15 (Bob with 12 and Dave with 9). Then .map() extracts just the name from each remaining entry. The result is ["Bob", "Dave"].Question 5: CRITICAL THINKING
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.Show answer
Object.keys() is generally more readable and safer because it automatically excludes inherited properties. Approach (A) with for...in might still be useful when you intentionally want to inspect inherited properties — for example, when debugging a prototype chain or when writing a utility function that needs to see all enumerable properties across the inheritance hierarchy. However, in most everyday code, approach (B) is preferred because it produces cleaner code, avoids the boilerplate of the hasOwnProperty() check, and returns a real array that supports chaining with .filter(), .map(), and other array methods.SUMMARY
Lesson Summary
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.