JavaScript Maps and Sets
Store unique values and keyed data with Set and Map, and hold weak references with WeakMap.
TL;DR
- Use
Setto store unique value collections and eliminate duplicates. - Use
Mapto match key-value pairs using any key type. - Query
sizeand iterate directly using standardfor-ofloops.
Set Basics
Set initializationCreates a new Set from an iterable, automatically filtering out duplicate values.
const numbers = new Set([1, 2, 2, 3]);
console.log(numbers); // Set { 1, 2, 3 }add()Adds a new unique value to the Set collection and returns the Set.
const colors = new Set();
colors.add("red").add("blue");has()Checks if a specific value exists in the Set using constant time lookup.
const exists = colors.has("red"); // truedelete() and clear()Removes individual items or deletes all elements from the Set collection.
colors.delete("red");
colors.clear();Map Basics
Map initializationCreates a Map storing key-value pairs, maintaining insertion order of keys.
const config = new Map([
["timeout", 5000],
["retries", 3]
]);set()Inserts or updates a value for a specific key in the Map.
const user = new Map();
user.set("name", "Alice");get()Retrieves the value associated with a specific key, returning undefined if missing.
const timeout = config.get("timeout"); // 5000has() checkVerifies if a key is present in the Map collection without reading it.
const hasKey = config.has("timeout"); // trueMap vs Object
Key typesMap allows objects and functions as keys, whereas objects coerce keys to strings.
const map = new Map();
const keyObj = { id: 1 };
map.set(keyObj, "metadata");
console.log(map.get(keyObj)); // "metadata"Size propertiesMap counts elements directly via size, whereas objects require key array length.
const map = new Map([["a", 1]]);
console.log(map.size); // 1
const obj = { a: 1 };
console.log(Object.keys(obj).length); // 1Iteration and Conversion
Set iterationLoops through Set values directly using a standard for-of loop.
const numbers = new Set([1, 2, 3]);
for (const num of numbers) {
console.log(num);
}Map iterationDestructures entries into key-value pairs during iteration loops.
const user = new Map([["name", "Alice"]]);
for (const [k, v] of user) {
console.log(k, v);
}Spread conversionsConverts collection elements back into standard arrays using the spread operator.
const set = new Set([1, 2]);
const arr = [...set]; // [1, 2]What WeakMap Is
WeakMap key valuesStores key-value entries where keys are object references.
const cache = new WeakMap();
const user = { id: 1 };
cache.set(user, { clicks: 3 });Weak referencesAllows garbage collection of key objects when references disappear.
let el = document.querySelector("#widget");
cache.set(el, { clicks: 0 });
el = null; // entry can be collected nowKey constraintsRequires object keys, throwing errors when primitives are passed.
// cache.set("key", 1); // TypeErrorTips
- Deduplicate an array instantly by wrapping it in a
Setand spreading it back. - Initialize a new
Mapdirectly from objects using the staticObject.entries()conversion method.
Warnings
- Remember that object keys in
Mapcollections are compared using strict reference identity matches. - Standard
JSON.stringify()serialization does not natively supportSetorMapcollections.
In Practice
Processes raw login attempts to return unique user lists and trace login frequencies using Set and Map collections.
- Deduplicate the list of raw usernames by instantiating a
Setcollection. - Spread the unique set items back into a standard username array.
- Create a new
Mapinstance to log individual user frequency totals. - Iterate through usernames, retrieving previous counts or defaulting to zero.
- Increment and update the login total for each user in the map.
function analyzeLogins(usernames) {
const uniqueUsers = [...new Set(usernames)];
const loginCounts = new Map();
for (const user of usernames) {
const count = loginCounts.get(user) ?? 0;
loginCounts.set(user, count + 1);
}
return {
uniqueUsers,
loginCounts
};
}FAQ
Use the has() method, which performs instant lookup check queries. This method is much faster than checking arrays with includes(). Set checks take constant time regardless of size.
Yes, you can use any value including objects and arrays as keys in a Map. These keys are matched by reference. Two separate empty objects are treated as two distinct keys.
Choose Map when keys are not strings or when insertion order must be preserved. A Map is also optimized for frequent additions and removals. Plain objects work better for simple static configs.
Map objects retain strong references to their keys, preventing garbage collection. WeakMap objects hold weak references, allowing keys to be collected. Keys must be objects, and iteration is prohibited.