Map vs Object

Map Preserves Insertion Order, Accepts Any Key Type, and Has a Built-in Size

Map vs Object

Understand when to reach for Map over a plain object: key types, iteration order guarantees, size tracking, and performance trade-offs.

4 min read Level 1/5 #dsa#hashing#map
What you'll learn
  • List the key differences between Map and a plain object
  • Choose the correct structure based on key type and iteration requirements
  • Measure Map size without counting keys manually

JavaScript gives you two built-in hash-table structures: Map and plain objects ({}). Both offer O(1) average lookup, but they differ in ways that matter for algorithmic code.

Key Types

Plain objects coerce all keys to strings (or Symbols). Map accepts any value as a key — including objects, functions, and numbers — without coercion.

const obj = {};
obj[1]    = "number key";
obj[true] = "boolean key";
console.log(Object.keys(obj)); // ["1", "true"]  — coerced!

const map = new Map();
const keyObj = { id: 42 };
map.set(keyObj, "object key");
map.set(1,      "number key");
map.set(true,   "boolean key");

console.log(map.get(keyObj));  // "object key"
console.log(map.get(1));       // "number key"
console.log(map.size);         // 3

Iteration Order

Map guarantees iteration in insertion order — always. Plain objects also preserve insertion order for string keys in modern engines, except for integer-like keys (e.g. “0”, “1”, “2”), which are sorted numerically first.

const obj = {};
obj["b"] = 2;
obj["a"] = 1;
obj["10"] = 10;
obj["2"]  = 2;
console.log(Object.keys(obj)); // ["2", "10", "b", "a"]  — integers first!

const map = new Map([["b", 2], ["a", 1], ["10", 10], ["2", 2]]);
console.log([...map.keys()]);  // ["b", "a", "10", "2"]  — insertion order

This surprises many developers. When key ordering matters, always use Map.

Size

Map exposes .size in O(1). With a plain object you must call Object.keys(obj).length, which is O(n).

Feature Comparison

FeatureMapPlain Object
Key typesAny valueString or Symbol
Insertion-order iterAlwaysExcept integer-like keys
Size.size — O(1)Object.keys().length — O(n)
Prototype pollutionNoneInherits from Object
JSON serialisableNo (needs custom logic)Yes
Spread / destructureVia Object.fromEntriesNative

When to Pick Which

Use Map when:

  • Keys are non-string values (DOM nodes, class instances, numbers).
  • You need guaranteed iteration order regardless of key shape.
  • You frequently read .size in a hot loop.
  • The data is purely algorithmic (frequency maps, adjacency maps).

Use a plain object when:

  • You need JSON serialisation out of the box.
  • You are modelling a static record with a fixed set of string keys.
  • You need destructuring or spread syntax directly.
// Frequency map — Map is the natural fit
function charFrequency(str) {
  const freq = new Map();
  for (const ch of str) {
    freq.set(ch, (freq.get(ch) ?? 0) + 1);
  }
  return freq;
}

console.log([...charFrequency("hello")]);
// [["h",1],["e",1],["l",2],["o",1]]

Up Next

Explore Set — the hash-table cousin that stores unique values and supports O(1) membership tests.

Sets →