Map vs Object in JavaScript: Complete Guide
Compare Map and Object in JavaScript across key types, performance, iteration, safety, and serialization. Learn which to choose for your data storage needs.
Both Map and plain objects store key-value pairs. For years, objects were the only option, so they became the default. But Map was added in ES6 to solve specific problems that objects have. The question is not which one is better overall, but which one fits your current task.
The Core Differences
| Map | Object | |
|---|---|---|
| Key types | Any value: objects, functions, primitives | Strings and Symbols only |
| Default keys | None (clean slate) | Inherited from prototype (toString, etc.) |
| Insertion order | Guaranteed, simple | Complex, varies by key type |
| Size | map.size (property, O(1)) | Object.keys(obj).length (O(n)) |
| Iteration | Directly iterable, for...of | Requires Object.keys/values/entries |
| Performance | Optimized for frequent add/delete | Optimized for static property access |
| JSON | Not serializable natively | Native JSON.stringify/parse |
| Prototype safety | No prototype chain interference | Risk of key collision with inherited properties |
Key Types: The Biggest Difference
Map accepts any value as a key, and it keeps that value exactly as given, whether it is an object, a function, or a number:
const map = new Map();
const keyObj = { id: 1 };
const keyFunc = () => "hello";
map.set(keyObj, "object key works");
map.set(keyFunc, "function key works");
map.set(42, "number key works");
console.log(map.get(keyObj)); // "object key works"An object cannot do the same thing, because every key you assign to it is coerced to a string via .toString() first. Two different objects both become the literal string "[object Object]" and collide:
const obj = {};
const keyObj = { id: 1 };
const anotherKeyObj = { id: 2 };
obj[keyObj] = "first";
obj[anotherKeyObj] = "second";
console.log(obj["[object Object]"]); // "second" (overwrote the first one)The Prototype Pollution Problem
Every plain object inherits properties from Object.prototype. If a key happens to match an inherited property name, you get unexpected behavior:
const obj = {};
obj["toString"] = "hello";
obj["constructor"] = "world";
console.log(obj.toString); // [Function: toString] (inherited, not "hello")
console.log(typeof obj.toString); // "function"Map has no such issue, because it does not inherit a set of default keys the way a plain object inherits from Object.prototype. It starts completely empty:
const map = new Map();
map.set("toString", "hello");
map.set("constructor", "world");
console.log(map.get("toString")); // "hello"
console.log(map.get("constructor")); // "world"This matters when keys come from user input, API responses, or file parsing. For more on Map basics, see the article on /javascript/javascript-map-object-complete-guide.
Iteration and Order
Map is designed for iteration. You can loop directly with for...of, and order matches insertion:
const map = new Map();
map.set("z", 1);
map.set("a", 2);
map.set("m", 3);
for (const [key, value] of map) {
console.log(key); // z, a, m (insertion order)
}Objects require extra steps to iterate, and the order of the resulting keys is less predictable than a Map's, especially once numeric-looking keys get involved:
const obj = { z: 1, a: 2, 3: "numeric" };
console.log(Object.keys(obj)); // ["3", "z", "a"] (numeric keys sort first!)Performance: When It Matters
Map is optimized for scenarios where entries are frequently added and removed. Object is optimized for static shapes where property names are known at parse time:
- Frequent mutations: Map is faster. Adding and deleting entries is O(1) on average.
- Static property access: Object is comparable, especially when the engine can optimize for known property shapes (hidden classes).
- Finding the size: map.size is instant. Object.keys(obj).length creates an array first.
For most everyday code, the performance difference is negligible. Choose based on the API and safety needs, not micro-benchmarks.
JSON Serialization
This is where Object has a clear advantage. JSON.stringify() works on objects but ignores Map:
const obj = { name: "Alex", age: 28 };
console.log(JSON.stringify(obj)); // {"name":"Alex","age":28}
const map = new Map([["name", "Alex"], ["age", 28]]);
console.log(JSON.stringify(map)); // {} (empty!)To serialize a Map, convert it to an array of entries first, then reverse the process with the Map constructor when you read it back:
const serialized = JSON.stringify([...map]);
console.log(serialized); // [["name","Alex"],["age",28]]
// Deserialize
const restored = new Map(JSON.parse(serialized));
console.log(restored.get("name")); // "Alex"If your data needs to survive JSON.stringify and JSON.parse round trips, stick with objects or handle the conversion manually. For techniques to iterate and transform objects, see the article on /javascript/javascript-object-keys-values-and-entries-guide.
When to Use Each
The differences covered so far come down to a few branching questions. Walk through them in order and you will land on the right collection for your situation:
The decision tree shows the primary trade-offs. In practice, many codebases use Object for configuration and data transfer, and Map for dynamic collections, caches, and situations where keys are not known ahead of time.
Rune AI
Key Insights
- Map accepts any type as keys; Object keys are strings or symbols.
- Map guarantees insertion order; Object order is complex and less reliable.
- Map is safe from prototype pollution; Object can collide with inherited properties.
- Map is iterable directly; Object requires Object.keys/values/entries.
- Object supports JSON serialization natively; Map requires manual conversion.
Frequently Asked Questions
Is Map faster than Object?
Can Map be serialized to JSON?
Should I always use Map instead of Object?
Conclusion
Map and Object overlap in purpose but diverge in key flexibility, safety, and performance characteristics. Choose Map when keys are dynamic, non-string, or user-provided. Choose Object for static shapes, JSON interchange, and classical key-value patterns. Knowing both lets you pick the right tool for each situation.| Scenario | Recommendation | |---|---| | Fixed set of string keys (config, options) | Object | | Data going to or from an API as JSON | Object | | Keys are anything other than strings | Map | | Keys are dynamic or from user input | Map | | Need to frequently add and remove entries | Map | | Need reliable insertion order | Map | | Building a cache or lookup table | Map | | Simple static record with known shape | Object |
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.