Skip to main content

Map vs object

Many people assume that a Map and a plain object {} are almost the same thing, but there are substantial differences between them. An Object is a general purpose data structure for storing properties whose keys are strings or symbols, while a Map is a specialized collection for storing "key to value" pairs with keys of any type and preserved insertion order.

Theory

TL;DR

  • Object keys are strings and symbols only, Map keys are any values.
  • A Map always returns elements in insertion order, an object sorts integer like keys.
  • Size: Object.keys(obj).length versus a plain map.size.
  • A Map is directly iterable with for...of, an object is not.
  • A Map is faster under frequent inserts and deletes.
  • A Map does not inherit from Object.prototype, so there are no clashes with toString or hasOwnProperty.
  • Conversion works both ways: new Map(Object.entries(obj)) and Object.fromEntries(map).

Quick example

javascript
const obj = {}; const map = new Map(); const keyObj = { id: 1 }; obj[keyObj] = 'object value'; map.set(keyObj, 'map value'); console.log(obj); // { "[object Object]": "object value" } console.log(map.get(keyObj)); // "map value"

In the object the key turned into the string "[object Object]", while in the Map it stayed a real object. If we added a second object as a key, in obj it would simply overwrite the first entry, because the resulting string would be identical.

Key types

FeatureObjectMap
KeysStrings or symbols onlyAny type (strings, numbers, objects, functions and so on)

This is the most important practical difference: only a Map lets you use an object or a function as a key and thereby attach data to a specific instance.

Order, size and iteration

Key order.

FeatureObjectMap
Key orderPartly guaranteed (ES6 and later)Always preserved

A Map always returns elements in insertion order, while an object behaves differently with numeric keys:

javascript
const obj = { 2: 'b', 1: 'a' }; console.log(Object.keys(obj)); // ["1", "2"] (numbers are sorted ascending)
javascript
const map = new Map([[2, 'b'], [1, 'a']]); console.log([...map.keys()]); // [2, 1] (order is preserved)

Size.

FeatureObjectMap
SizeObject.keys(obj).lengthmap.size
javascript
const map = new Map([['a', 1], ['b', 2]]); console.log(map.size); // 2

The difference is not only convenience: Object.keys() builds an intermediate array, while size is just reading a counter.

Iterability.

FeatureObjectMap
Iterated directlyNoYes
javascript
const map = new Map([['x', 10], ['y', 20]]); for (const [key, value] of map) { console.log(key, value); } // x 10 // y 20

For an object you have to call Object.keys(), Object.entries() and similar methods.

Performance and prototype

FeatureObjectMap
Frequent inserts and deletesSlowerFaster
Iterating over elementsAwkwardConvenient with for...of

A Map is optimized exactly for frequent additions, deletions and traversal, whereas engines optimize objects for a stable "shape" with a known set of fields.

FeatureObjectMap
Inherits from Object.prototypeYesNo
Can clash with methods (toString, hasOwnProperty)YesNo

A Map carries no "junk" in the form of built in methods, so any key is safe to use. In an object a key such as "hasOwnProperty" or "__proto__" can break your checks.

Converting between them

javascript
const obj = { a: 1, b: 2 }; const map = new Map(Object.entries(obj)); console.log(map); // Map(2) { 'a' => 1, 'b' => 2 } const backToObj = Object.fromEntries(map); console.log(backToObj); // { a: 1, b: 2 }

Object.entries() and Object.fromEntries() make conversion in both directions easy. This is also how you serialize a Map, since JSON.stringify(map) on its own yields {}.

What to use and when

UseWhen
Objecta data structure with fixed properties (a user model, for instance)
Mapdynamic keys, keys of any type, caches, frequent add and delete operations

In short:

FeatureObjectMap
Key typesstring or symbolany type
Key orderpartly orderedpreserved
Sizecounted manually.size
Iterabilityvia Object.keys()directly (for...of)
Performancelowerhigher
Use casestatic datadynamic collections

Common mistakes

  • Using an object as a key of a plain object. The key silently becomes the string "[object Object]" and all objects collapse into a single entry.
  • Relying on the order of numeric object keys. Integer like keys are always sorted ascending, regardless of insertion order.
  • Writing map.length or map['key']. The first is undefined, the second creates a property outside the collection; the correct forms are map.size and map.get('key').
  • Serializing a Map directly. JSON.stringify(map) returns {}, you need Object.fromEntries(map) or an array from [...map] first.
  • Reaching for a Map everywhere "because it is faster". For a small fixed model an object is more convenient: destructuring, shorthand syntax, native JSON support.
  • Forgetting that a Map holds keys strongly. Object keys will not leave memory while the Map itself is alive; for weak references there is WeakMap.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.