In short
Plain objects are fine for fixed records. When you need a real lookup table where keys come and go, and can be anything, Map is the better tool.
A built-in key-value collection (like an object) but with keys of any type, guaranteed insertion order, and a cleaner API (`.get`, `.set`, `.has`). `Map` is especially useful when keys are not limited to strings or when explicit collection operations and reliable insertion order make the intent clearer than a plain object.

Think of it like this
The kirana udhaar register
The kirana uncle keeps a register: each customer's name next to what they owe. He looks up a name, updates the amount and crosses names out when they pay. A Map is that register, except the "name" can be anything, even an object.
Watch it happen
Working with the khata Map
set("Ravi", 250)
1/6A new entry: key "Ravi", value 250.
The big ideas
What you need to know
Any key type
Objects turn keys into strings. A Map keeps keys as they are: numbers, objects, even functions.
Clear methods
set, get, has, delete and clear, plus a size property. No guessing with Object.keys(obj).length.
Keeps insertion order
Looping over a Map gives entries in the order you added them.
Built for add and remove
For lookups that change often, Map is designed for it and has no inherited keys to clash with.
See it in code
Walk through the code
1const khata = new Map();2khata.set("Ravi", 250);3khata.set("Neha", 120);4khata.set("Ravi", khata.get("Ravi") + 50); // update5 6console.log(khata.get("Ravi")); // 3007console.log(khata.has("Amit")); // false8console.log(khata.size); // 29 10for (const [name, due] of khata) console.log(name, due);11// Ravi 30012// Neha 12013 14const asObject = Object.fromEntries(khata); // { Ravi: 300, Neha: 120 }1/4Create the Map, add two entries, then update Ravi.
Looping gives you [key, value] pairs, so destructuring them in the for...of reads nicely. Object.fromEntries turns a Map back into a plain object.
Save yourself the pain
Common mistakes
Oops
Writing map["Ravi"] = 250.
Do this instead
That sets a normal property, not a Map entry, and size stays 0. Always use map.set("Ravi", 250).
Oops
Calling JSON.stringify(map) and getting {}.
Do this instead
Maps don't turn into JSON directly. Convert first: JSON.stringify(Object.fromEntries(map)).
Your mission
Word counter
Quick check
What does this log? const m = new Map(); m["a"] = 1; console.log(m.size);
Go deeper
- 1Build a small cache using a `Map` instead of a plain object. Keep the first version small, then add one improvement after the core behavior works.
- 2Try using an object (not just a string) as a Map key. Inspect the result in DevTools or the console and explain what you observed.
- 3Compare iterating a `Map` vs a plain object with `for...of`.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.