Episode 1 — Fundamentals / 1.24 — Object Methods
1.24.a — Object.entries()
In one sentence:
Object.entries(obj)returns an array of[key, value]pairs from an object's own enumerable string-keyed properties, enabling powerful iteration and transformation patterns.
Navigation: <- 1.24 Overview . 1.24.b — Object.assign ->
1. What does Object.entries() do?
Object.entries() takes an object and returns a two-dimensional array where each inner array is a [key, value] pair.
const user = { name: "Alice", age: 30, role: "admin" };
const entries = Object.entries(user);
console.log(entries);
// [
// ["name", "Alice"],
// ["age", 30],
// ["role", "admin"]
// ]
Each entry is a new array — mutating it does not affect the original object.
2. Syntax and return type
Object.entries(obj)
| Parameter | Description |
|---|---|
obj | The object whose own enumerable string-keyed [key, value] pairs are returned |
| Returns | Array<[string, any]> — an array of two-element arrays |
If obj is not an object, it is coerced to one:
Object.entries("hi"); // [["0", "h"], ["1", "i"]]
Object.entries(42); // [] (numbers have no enumerable props)
Object.entries(true); // []
3. Only own, enumerable, string-keyed properties
Object.entries() skips three categories of properties:
| Skipped | Example |
|---|---|
| Inherited properties | Properties from the prototype chain |
| Non-enumerable properties | Properties defined with enumerable: false |
| Symbol-keyed properties | Properties with Symbol keys |
const parent = { inherited: true };
const child = Object.create(parent);
child.own = "yes";
Object.defineProperty(child, "hidden", {
value: "secret",
enumerable: false,
});
child[Symbol("id")] = 99;
console.log(Object.entries(child));
// [["own", "yes"]]
// inherited, hidden, and Symbol properties are excluded
4. Iterating with for...of and destructuring
The most common pattern — destructure each entry into key and value:
const scores = { math: 95, science: 88, english: 92 };
for (const [subject, score] of Object.entries(scores)) {
console.log(`${subject}: ${score}`);
}
// math: 95
// science: 88
// english: 92
This is cleaner than for...in because:
- No need for
hasOwnPropertycheck (entries are already own properties) - You get both key and value directly
- It works with
constdestructuring
5. Converting an object to a Map
Map constructor accepts an iterable of [key, value] pairs — exactly what Object.entries() produces:
const config = { theme: "dark", lang: "en", debug: false };
const configMap = new Map(Object.entries(config));
console.log(configMap.get("theme")); // "dark"
console.log(configMap.size); // 3
Why convert? Maps preserve insertion order for all key types, have .size, and perform better for frequent additions/deletions.
6. Transformation pipelines: entries -> map/filter -> fromEntries
The real power of Object.entries() emerges when combined with array methods and Object.fromEntries():
Filter object properties by value
const inventory = { apples: 5, bananas: 0, cherries: 12, dates: 0 };
const inStock = Object.fromEntries(
Object.entries(inventory).filter(([_, qty]) => qty > 0)
);
console.log(inStock);
// { apples: 5, cherries: 12 }
Transform all values
const prices = { shirt: 20, pants: 40, hat: 15 };
const withTax = Object.fromEntries(
Object.entries(prices).map(([item, price]) => [item, price * 1.1])
);
console.log(withTax);
// { shirt: 22, pants: 44, hat: 16.5 }
Rename keys
const apiResponse = { first_name: "Alice", last_name: "Smith" };
const camelCased = Object.fromEntries(
Object.entries(apiResponse).map(([key, val]) => [
key.replace(/_([a-z])/g, (_, c) => c.toUpperCase()),
val,
])
);
console.log(camelCased);
// { firstName: "Alice", lastName: "Smith" }
7. Comparison with Object.keys() and Object.values()
| Method | Returns | Use when you need |
|---|---|---|
Object.keys(obj) | ["key1", "key2", ...] | Only property names |
Object.values(obj) | [val1, val2, ...] | Only property values |
Object.entries(obj) | [["key1", val1], ...] | Both keys and values together |
All three share the same rules: own, enumerable, string-keyed, same order.
const user = { name: "Alice", age: 30 };
Object.keys(user); // ["name", "age"]
Object.values(user); // ["Alice", 30]
Object.entries(user); // [["name", "Alice"], ["age", 30]]
8. Real-world examples
Logging all properties
function logObject(label, obj) {
console.group(label);
for (const [key, value] of Object.entries(obj)) {
console.log(` ${key}: ${JSON.stringify(value)}`);
}
console.groupEnd();
}
logObject("User", { name: "Bob", age: 25, active: true });
// User
// name: "Bob"
// age: 25
// active: true
Converting object to query string
function toQueryString(params) {
return Object.entries(params)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join("&");
}
console.log(toQueryString({ search: "hello world", page: 2, lang: "en" }));
// "search=hello%20world&page=2&lang=en"
Filtering object by value type
const mixed = { a: 1, b: "two", c: 3, d: "four", e: 5 };
const numbersOnly = Object.fromEntries(
Object.entries(mixed).filter(([_, v]) => typeof v === "number")
);
console.log(numbersOnly);
// { a: 1, c: 3, e: 5 }
Building an HTML table from an object
function objectToTable(obj) {
const rows = Object.entries(obj)
.map(([key, val]) => `<tr><td>${key}</td><td>${val}</td></tr>`)
.join("\n");
return `<table>\n<tr><th>Key</th><th>Value</th></tr>\n${rows}\n</table>`;
}
Comparing two objects for differences
function getDifferences(objA, objB) {
return Object.fromEntries(
Object.entries(objA).filter(([key, val]) => objB[key] !== val)
);
}
const before = { name: "Alice", age: 30, role: "user" };
const after = { name: "Alice", age: 31, role: "admin" };
console.log(getDifferences(before, after));
// { age: 30, role: "user" } -- values from objA that differ
9. Property order guarantee
Object.entries() returns properties in the same order as for...in (minus inherited):
- Integer-like keys in ascending numeric order (
"0","1","2", ...) - String keys in insertion order
- (Symbol keys are excluded entirely)
const obj = { b: 2, 2: "two", a: 1, 1: "one" };
console.log(Object.entries(obj));
// [["1", "one"], ["2", "two"], ["b", 2], ["a", 1]]
// Integer keys first (sorted), then string keys (insertion order)
10. Edge cases
// Empty object
Object.entries({}); // []
// null / undefined — throws TypeError
// Object.entries(null); // TypeError!
// Object.entries(undefined); // TypeError!
// Array (arrays are objects)
Object.entries(["a", "b"]); // [["0", "a"], ["1", "b"]]
// Object with numeric keys
Object.entries({ 10: "ten", 2: "two", 1: "one" });
// [["1", "one"], ["2", "two"], ["10", "ten"]]
Key takeaways
Object.entries(obj)returns an array of[key, value]pairs for own enumerable string-keyed properties.- Destructure in
for...ofloops:for (const [key, value] of Object.entries(obj)). - Pipe through
map/filterthenObject.fromEntries()to transform objects functionally. - Convert to Map with
new Map(Object.entries(obj)). - Inherited, non-enumerable, and Symbol-keyed properties are excluded.
Explain-It Challenge
Explain without notes:
- What does
Object.entries({ a: 1, b: 2 })return? What is the type of each inner element? - How would you filter an object to keep only properties with truthy values using
entriesandfromEntries? - Why is
for (const [k, v] of Object.entries(obj))preferred overfor...inin many cases?
Navigation: <- 1.24 Overview . 1.24.b — Object.assign ->