JavaScript Map Object: Complete Guide
Learn the JavaScript Map object: a key-value collection that accepts any type as a key, preserves insertion order, and outperforms plain objects for frequent data operations.
A Map is a built-in JavaScript collection that stores key-value pairs, similar to a plain object, but with important advantages: keys can be any type (not just strings), insertion order is guaranteed, and it is optimized for frequent additions and removals.
You create a Map with the new Map() constructor and interact with it through dedicated methods rather than dot or bracket notation.
Creating a Map and Basic Operations
An empty Map starts out with no entries, and you add to it with set() instead of assigning properties directly:
const map = new Map();
map.set("name", "Alex"); // Add an entry
map.set("role", "admin");
console.log(map.get("name")); // "Alex"
console.log(map.has("role")); // true
console.log(map.size); // 2The same map object supports removing a single entry or clearing everything at once, and size updates automatically either way:
map.delete("role"); // Remove an entry
console.log(map.has("role")); // false
console.log(map.size); // 1
map.clear(); // Remove everything
console.log(map.size); // 0| Method | Description |
|---|---|
map.set(key, value) | Adds or updates an entry. Returns the map (chainable). |
map.get(key) | Returns the value for the key, or undefined if not found. |
map.has(key) | Returns true if the key exists. |
map.delete(key) | Removes the entry. Returns true if it existed. |
map.clear() | Removes all entries. |
map.size | The number of entries (property, not a method). |
Keys Can Be Any Type
This is the feature that sets Map apart from plain objects. You can use objects, functions, numbers, and even NaN as keys:
const cache = new Map();
const userObj = { id: 1 };
const fetchFn = () => "data";
cache.set(userObj, { name: "Taylor" });
cache.set(fetchFn, "cached result");
cache.set(42, "the answer");
console.log(cache.get(userObj)); // { name: "Taylor" }
console.log(cache.get(fetchFn)); // "cached result"Keys are compared by identity for objects and by SameValueZero for primitives. This means NaN works as a key even though NaN !== NaN:
const map = new Map();
map.set(NaN, "not a number");
console.log(map.get(NaN)); // "not a number"
console.log(map.get(Number("foo"))); // "not a number"This identity-based comparison has a practical consequence: two different object literals with the same content are treated as different keys, because they are different references in memory:
const map = new Map();
map.set({}, "first");
console.log(map.get({})); // undefined (different object reference)Initializing a Map from an Array
You do not have to build a Map one set() call at a time. Pass an array of key-value pairs directly to the constructor, and it fills the Map in one step:
const map = new Map([
["name", "Riley"],
["age", 30],
["active", true]
]);
console.log(map.get("name")); // "Riley"
console.log(map.size); // 3This pairs well with Object.entries() for converting plain objects to Maps. For more on that pattern, see the article on /javascript/javascript-object-keys-values-and-entries-guide.
Iterating Over a Map
Map is iterable. You can use for...of directly, which yields key-value pairs:
const scores = new Map([
["math", 92],
["science", 87],
["english", 95]
]);
for (const [subject, score] of scores) {
console.log(subject + ": " + score);
}When you only need the keys or only the values, .keys() and .values() give you a focused iterator instead of the full pair:
for (const subject of scores.keys()) {
console.log(subject);
}
for (const score of scores.values()) {
console.log(score);
}.forEach() is another option, useful when you already have a callback-based iteration pattern elsewhere in the codebase and want the Map version to look the same:
scores.forEach((score, subject) => {
console.log(subject + " -> " + score);
});Note the forEach callback order is (value, key). This matches array forEach, which calls back with (element, index) in that same value-first, key-second order, so the two methods feel consistent even though a Map's keys are not always numeric.
Cloning and Merging Maps
Clone a Map by passing it to the constructor:
const original = new Map([["x", 10], ["y", 20]]);
const clone = new Map(original);
clone.set("x", 99);
console.log(original.get("x")); // 10 (independent)Merge two Maps with the spread operator, the same way you would merge two plain objects. When both maps share a key, the later one wins:
const first = new Map([["a", 1], ["b", 2]]);
const second = new Map([["b", 99], ["c", 3]]);
const merged = new Map([...first, ...second]);
console.log(merged.get("b")); // 99 (later value wins)Spreading a Map produces an array of key-value pairs, which the constructor accepts.
Map vs Object: When to Use Each
The decision comes down to key types, performance needs, and safety. If any of these apply, choose Map:
| Scenario | Why Map |
|---|---|
| Keys are not strings | Map accepts objects, functions, numbers as keys |
| Frequent additions and removals | Map is optimized for dynamic data |
| Keys come from user input | No risk of prototype pollution |
| Need reliable insertion order | Map guarantees iteration order |
| Need the count quickly | map.size is O(1), Object.keys(obj).length is O(n) |
Plain objects are the right choice when you have a fixed set of string keys, need JSON serialization, or are working with APIs that expect objects.
The Most Common Map Mistake
Setting a property on a Map with bracket or dot notation does not use the Map's data structure. It sets a regular object property that is invisible to Map methods:
const map = new Map();
// Wrong: this sets a regular object property, not a Map entry
map["name"] = "Alex";
console.log(map.get("name")); // undefined
console.log(map.has("name")); // false
console.log(map.name); // "Alex" (plain property, not Map data)Always use map.set(key, value) and map.get(key). Never use bracket notation or dot notation to store data in a Map.
Converting Between Map and Object
Some APIs and JSON payloads expect a plain object, so you will occasionally need to convert in either direction. Going from Map to Object uses Object.fromEntries(), since a Map is already iterable as key-value pairs:
const map = new Map([["theme", "dark"], ["fontSize", 16]]);
const obj = Object.fromEntries(map);
console.log(obj); // { theme: "dark", fontSize: 16 }Going the other way, from Object to Map, uses Object.entries() to produce the key-value pairs that the Map constructor already knows how to accept:
const obj = { theme: "dark", fontSize: 16 };
const map = new Map(Object.entries(obj));
console.log(map.get("theme")); // "dark"For the companion collection type that stores unique values without keys, see the article on /javascript/javascript-set-object-complete-guide.
Rune AI
Key Insights
- A Map holds key-value pairs where keys can be any type, including objects and functions.
- Use set(key, value) and get(key) to add and retrieve entries.
- Map preserves insertion order and has a convenient size property.
- Iterate with for...of, forEach(), keys(), values(), or entries().
- Never set properties on a Map with bracket notation -- use set() instead.
Frequently Asked Questions
When should I use a Map instead of an Object?
Can I use objects as keys in a Map?
Does Map preserve insertion order?
Conclusion
Map is the right key-value collection when you need non-string keys, guaranteed insertion order, frequent additions and removals, or protection from inherited property collisions. For simple static data with string keys, a plain object is fine. But when performance, key flexibility, or safety matter, reach for Map.
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.