Object.fromEntries()

ES2019+

Transforms a list of [key, value] pairs — from an array, a Map, URLSearchParams, or any iterable — into a new plain object. It is the inverse of Object.entries() and the final step of the filter-map-rebuild pattern for immutable object transformations.

Syntax

Object.fromEntries(iterable)

Parameters

iterable Iterable

An iterable such as Array or Map containing key-value pairs

Return Value

Object

A new object whose properties are given by the entries

Examples

JavaScript
const entries = [['a', 1], ['b', 2]];
console.log(Object.fromEntries(entries));
Output:
// { a: 1, b: 2 }

📌 When to Use

Use Object.fromEntries() whenever data arrives as key-value pairs but the rest of your code wants a plain object. The three canonical sources are: the output of Object.entries() after array transformations (completing the entries-transform-fromEntries round trip), Map instances that must become JSON-serializable objects, and URLSearchParams when parsing a query string into an options object in one line. It also converts arrays of tuples produced by zip-style logic — for example pairing a list of column names with a row of values from a CSV — into records. Because it builds a brand-new object, it fits immutable update patterns: derive a filtered or renamed variant of a config without touching the original, then store the result in state safely. Prefer it over a manual reduce((acc, [k, v]) => { acc[k] = v; return acc; }, {}) loop, which does the same thing with more ceremony and more room for mistakes. Skip the round trip entirely when a single known property changes — a spread with an override like { ...obj, name: value } is simpler and faster than decomposing and rebuilding the whole object from entries.

⚠️ Common Mistakes

Expecting deep conversion of nested Maps - Object.fromEntries(map) only converts the top level. If the values are themselves Maps, or contain Maps, they stay Maps inside the result; write a recursive converter when you need a fully plain-object tree for JSON serialization.

Losing data when converting URLSearchParams with repeated keys - a query like "?tag=a&tag=b" collapses to { tag: "b" } because later pairs overwrite earlier ones. Use params.getAll("tag") for multi-value parameters instead of relying on the fromEntries result alone.

Passing an array without proper [key, value] structure - each element must be a two-element array or the conversion will fail.

Forgetting that duplicate keys will be overwritten - the last occurrence wins, just like object literal behavior.

Not handling non-string keys - Object.fromEntries() converts all keys to strings, which may cause unexpected behavior with Symbol or number keys.

✅ Best Practices

Build objects from parallel arrays by zipping first: Object.fromEntries(headers.map((h, i) => [h, row[i]])) turns CSV headers and a data row into a record object without an index-juggling loop, and reads as a single declarative statement.

Keep the entries round trip pure - inside the map() step, return new [key, value] tuples rather than mutating shared values, so the rebuilt object is a true independent snapshot at the top level and safe to store in application state.

After building objects from external pair data, freeze or validate before sharing: Object.freeze(Object.fromEntries(pairs)) hands consumers a locked snapshot, and running the result through a schema validator catches surprises like duplicate keys collapsing or numeric keys being reordered - cheap insurance at module boundaries where pair-shaped data enters from CSV parsers, query strings, or spreadsheets.

Use the entries-transform-fromEntries pattern for immutable object updates: Object.fromEntries(Object.entries(obj).map(...))

Parse URL parameters elegantly: Object.fromEntries(new URLSearchParams(queryString))

Convert Map to object when you need JSON serialization or object-specific operations.

⚡ Performance Notes

Object.fromEntries() runs in O(n) and creates one new object plus a property store sized to the entries. The cost that dominates in practice is the pipeline around it: Object.entries() allocates pair arrays, map() and filter() allocate intermediate arrays, and fromEntries() walks the final list. At config-object scale (tens of keys) this is negligible; when transforming thousands of records per frame, collapse the pipeline into a single reduce() or a plain for loop that assigns onto an accumulator object to cut allocations several-fold. Building many objects with identical keys in identical order also helps the engine share hidden classes between them, keeping downstream property access monomorphic and fast — another reason to keep transformation pipelines deterministic about key order rather than conditionally adding keys.

🌍 Real World Example

URL Query String Parser

This snippet turns a raw URL query string into a typed, safe options object in three explicit stages. URLSearchParams handles the percent-decoding and Object.fromEntries() converts it into a plain object; a filter pass then removes sensitive parameters like tokens before the object is logged or stored; finally a map pass converts numeric strings into real numbers. Each stage is a standalone entries round trip, so you can lift any of them into reusable helpers and apply the same pipeline to other endpoints.

const url = 'https://example.com?page=1&sort=date&token=abc123&limit=10';
const queryString = url.split('?')[1];

// Parse query string to object
const params = Object.fromEntries(new URLSearchParams(queryString));
console.log(params);
// { page: '1', sort: 'date', token: 'abc123', limit: '10' }

// Filter out sensitive parameters
const sensitiveKeys = ['token', 'password', 'secret'];
const safeParams = Object.fromEntries(
  Object.entries(params).filter(([key]) => !sensitiveKeys.includes(key))
);
console.log(safeParams);
// { page: '1', sort: 'date', limit: '10' }

// Convert string numbers to actual numbers
const typedParams = Object.fromEntries(
  Object.entries(safeParams).map(([key, value]) => [
    key,
    !isNaN(value) ? Number(value) : value
  ])
);
console.log(typedParams);
// { page: 1, sort: 'date', limit: 10 }

Related Methods