A Map stores pairs: a key and the value that goes with it. Look up the key, get the value back. That sounds like a plain object, and often an object is fine. But Maps are built specifically for this job, and they handle several situations that objects handle badly.
// Empty, then fill it
const prices = new Map();
prices.set("apple", 0.5);
prices.set("bread", 3.25);
// Or start with an array of [key, value] pairs
const capitals = new Map([
["France", "Paris"],
["Japan", "Tokyo"],
["Kenya", "Nairobi"]
]);
console.log(capitals.get("Japan"));
console.log(capitals.size);
const stock = new Map();
stock.set("pens", 40); // add
stock.set("pens", 35); // same key: replaces the value
stock.get("pens"); // 35
stock.get("tape"); // undefined (no such key)
stock.has("pens"); // true
stock.delete("pens"); // true
stock.size; // 0
get and set, not brackets. stock["pens"] = 40 does not add anything to the Map; it sticks an ordinary property on the Map object, and get("pens") will not find it.
Many languages call this kind of collection a dictionary. In JavaScript, a Map is a kind of object, and as with Sets, instanceof identifies it:
console.log(typeof capitals);
console.log(capitals instanceof Map);
1. Keys can be anything. Object keys are always turned into strings. Map keys keep their type, and can even be objects:
const obj = {};
obj[1] = "number one";
obj["1"] = "string one"; // overwrote it! 1 became "1"
console.log(Object.keys(obj)); // ["1"]
const map = new Map();
map.set(1, "number one");
map.set("1", "string one");
console.log(map.size); // 2 (two separate keys)
// Objects as keys: attach data to an object without changing it
const ava = { name: "Ava" };
const ben = { name: "Ben" };
const scores = new Map();
scores.set(ava, 92);
scores.set(ben, 85);
console.log(scores.get(ben)); // 85
2. No hidden keys. Objects come with built-in properties inherited from Object. A key like "toString" or "constructor" can collide with them. A new Map starts truly empty.
const words = {};
console.log("constructor" in words); // true (inherited, surprise!)
const wordMap = new Map();
console.log(wordMap.has("constructor")); // false
3. Size and order are built in. A Map has size and always loops in the order keys were added.
4. Maps loop directly. for...of works on a Map as it is. A plain object needs Object.keys, Object.entries, or for...in first.
5. Built for change. Maps are optimized for adding and removing entries often, such as a live list of who is online.
| Use an object when... | Use a Map when... |
|---|---|
| It describes one thing with fixed fields (a user, a product) | It is a lookup table that grows and shrinks |
| You know the key names while writing code | Keys come from data or user input |
| You need to save it as JSON | Keys are not strings (numbers, objects) |
Each loop step gives a [key, value] pair, which you can unpack right in the loop with destructuring (from JS Object Display):
for (const [country, city] of capitals) {
console.log(`${city} is the capital of ${country}`);
}
const words = "the cat and the hat and the bat".split(" ");
const counts = new Map();
for (const w of words) {
counts.set(w, (counts.get(w) ?? 0) + 1);
}
console.log(counts);
What does this log?
const m = new Map();
m.set(1, "number");
m.set("1", "string");
console.log(m.size);
2. Map keys keep their type, so 1 and "1" are different keys. In a plain object they would be the same key.What does this log?
const m = new Map();
m["x"] = 5;
console.log(m.get("x"), m.size);
undefined 0. Brackets add an ordinary property to the Map object, not an entry. Use m.set("x", 5).Which is true about Maps?
length propertysize.