jsguides

Object.entries()

Object.entries(obj)

Object.entries() returns an array of a given object’s own enumerable string-keyed property [key, value] pairs. The order matches that of a for...in loop, except inherited properties are excluded.

Syntax

Object.entries(obj)

Parameters

ParameterTypeDefaultDescription
objObjectrequiredThe object whose own enumerable string-keyed property [key, value] pairs are to be returned.

Return Value

An array of [key, value] pairs for each of the object’s own enumerable string-keyed properties.

Examples

Basic usage

const obj = { a: 1, b: 2, c: 3 };

console.log(Object.entries(obj));
// [['a', 1], ['b', 2], ['c', 3]]

The raw array of pairs is useful on its own, but the real power comes from combining entries() with destructuring. Each element is a two-item array, so a for...of loop with [key, value] gives you named access to both parts.

Destructuring in a loop

const user = { name: 'Alice', age: 30, role: 'admin' };

for (const [key, value] of Object.entries(user)) {
  console.log(`${key}: ${value}`);
}
// name: Alice
// age: 30
// role: admin

Destructuring in the loop declaration keeps the iteration body clean — you refer to key and value directly instead of indexing into pair[0] and pair[1]. The same pair structure makes entries() a natural input for the Map constructor, which accepts an iterable of [key, value] pairs.

Converting to a Map

const obj = { one: 1, two: 2, three: 3 };

const map = new Map(Object.entries(obj));
console.log(map.get('two'));
// 2

A Map created this way has the same keys and values as the original object, but with Map semantics — keys can be any type, iteration order is guaranteed to match insertion order, and the size is available via .size. When you need those benefits, converting through entries() is the shortest path.

Non-enumerable properties are excluded

const obj = Object.create({}, {
  hidden: { value: 'secret', enumerable: false },
  visible: { value: 'public', enumerable: true }
});

console.log(Object.entries(obj));
// [['visible', 'public']]

The exclusion of non-enumerable properties is a feature, not a limitation — it means entries() gives you the same view of an object that JSON.stringify and most serialization code see. Symbols are also excluded. For a complete inventory of all own properties regardless of enumerability, use Object.getOwnPropertyNames() and Object.getOwnPropertySymbols() instead.

Common Patterns

Filtering object properties

const scores = { alice: 85, bob: 42, charlie: 91, diana: 58 };

const passing = Object.fromEntries(
  Object.entries(scores).filter(([, score]) => score >= 60)
);

console.log(passing);
// { alice: 85, charlie: 91 }

The filter + fromEntries pipeline is a clean way to remove unwanted properties without mutating the original object. Because fromEntries is the inverse of entries(), you can chain any array method between them — filter to drop properties, map to change values, or both at once.

Transforming values

const prices = { apple: 1.5, banana: 0.75, cherry: 3.0 };

const discounted = Object.fromEntries(
  Object.entries(prices).map(([item, price]) => [item, price * 0.9])
);

console.log(discounted);
// { apple: 1.35, banana: 0.675, cherry: 2.7 }

The map step transforms each [key, value] pair into a new pair with a modified value — the keys stay the same, so the reconstructed object has the same shape with updated numbers. You can apply any transformation logic inside the mapper, including type conversions or computed values.

Sorting object by value

const scores = { alice: 85, bob: 42, charlie: 91 };

const sorted = Object.fromEntries(
  Object.entries(scores).sort(([, a], [, b]) => b - a)
);

console.log(sorted);
// { charlie: 91, alice: 85, bob: 42 }

Sorting by value is a pattern that would be awkward without entries() — you would need a separate array of keys sorted by a lookup into the object. With entries(), the sort comparator receives both the keys and the values directly, and fromEntries() rebuilds the object in the sorted order.

Property ordering

Object.entries() returns properties in the same order as for...in: integer keys in ascending numeric order first, then string keys in insertion order. Symbol keys are never included — use Object.getOwnPropertySymbols() if you need those.

const obj = { b: 2, a: 1, 10: 'ten', 2: 'two' };
console.log(Object.entries(obj));
// [['2', 'two'], ['10', 'ten'], ['b', 2], ['a', 1]]

Object.entries() vs for…in

for...in also iterates enumerable string-keyed properties, but it includes inherited properties from the prototype chain. Object.entries() only returns own properties, which is almost always what you want. If you need inherited properties, use for...in; otherwise, prefer Object.entries() for its predictability.

const parent = { inherited: true };
const child = Object.create(parent);
child.own = 'yes';

console.log(Object.entries(child)); // [['own', 'yes']] — no inherited
for (const k in child) console.log(k); // 'own', 'inherited'

Object.entries() vs Object.keys()

When you need both the key and value, use entries(). When you only need the keys, keys() is more explicit and slightly faster because it does not allocate the [key, value] tuples.

Why Object.entries() is so useful

Object.entries() is the most convenient bridge between object-shaped data and array-oriented processing. Because the result is an array of pairs, you can destructure it directly in loops or feed it into map(), filter(), and fromEntries() without extra work. That makes it a natural choice for transforming configuration objects, sorting by value, or moving data into another container type.

Primitive coercion

Like Object.keys(), entries() coerces non-object arguments. Strings are converted to array-index keyed entries; numbers return an empty array. Passing null or undefined throws a TypeError. In TypeScript these edge cases are typed away, but in plain JavaScript you may encounter them when working with dynamic data:

Object.entries('abc'); // [['0','a'],['1','b'],['2','c']]
Object.entries(42);   // []
Object.entries(null); // TypeError

Return value as a snapshot

Object.entries() returns a plain array — not a live view of the object. Modifying the object after calling entries() has no effect on the returned array, and modifying the array does not affect the object. This snapshot behaviour makes entries() safe to use while transforming an object, since you are working from a stable copy.

See Also