JavaScript provides several built-in data structures for storing and managing information. In addition to arrays and objects, modern JavaScript includes Map, Set, WeakMap, and WeakSet.
These data structures solve different problems. A Map stores key-value pairs, a Set stores unique values, a WeakMap associates data with eligible object keys without strongly retaining those keys, and a WeakSet tracks eligible object references without strongly retaining them.
Understanding these data structures helps you write cleaner, more efficient, and more maintainable JavaScript code.
What Is a Map in JavaScript?
A Map is a built-in JavaScript data structure that stores information as key-value pairs. Each key is unique, and each key is associated with a value.
Unlike regular JavaScript objects, Maps can use values of different types as keys, including strings, numbers, objects, and functions.
Creating a Map
You can create a Map using the Map constructor.
const student = new Map();
student.set("name", "Karim");
student.set("age", 22);
student.set("course", "JavaScript");
console.log(student);
Output:
Map(3) {
'name' => 'Karim',
'age' => 22,
'course' => 'JavaScript'
}
The set() method adds a new key-value pair to the Map.
Getting Values From a Map
Use the get() method to retrieve a value by its key.
const student = new Map();
student.set("name", "Karim");
student.set("age", 22);
console.log(student.get("name"));
console.log(student.get("age"));
Output:
Karim
22
If the specified key does not exist, get() returns undefined.
Checking Whether a Key Exists
Use the has() method to check whether a key is present.
const products = new Map();
products.set("Laptop", 50000);
products.set("Mouse", 800);
console.log(products.has("Laptop"));
console.log(products.has("Keyboard"));
Output:
true
false
Updating and Deleting Map Entries
Calling set() with an existing key updates its value.
const prices = new Map();
prices.set("Laptop", 50000);
prices.set("Laptop", 45000);
console.log(prices.get("Laptop"));
Output:
45000
Use delete() to remove an entry and clear() to remove all entries.
const prices = new Map([
["Laptop", 45000],
["Mouse", 800]
]);
prices.delete("Mouse");
console.log(prices.size);
prices.clear();
console.log(prices.size);
Output:
1
0
The size property returns the number of entries in a Map.
Using Objects as Map Keys
One useful feature of Map is that objects can be used as keys.
const user = { id: 101 };
const roles = new Map();
roles.set(user, "Administrator");
console.log(roles.get(user));
Output:
Administrator
Object keys are compared by identity, not by their property contents.
console.log(roles.get({ id: 101 }));
Output:
undefined
The second object contains the same property, but it is a different object reference.
Looping Through a Map
Maps preserve the insertion order of their entries and can be iterated using for...of.
const scores = new Map([
["Karim", 90],
["Ayesha", 85],
["Rahul", 88]
]);
for (const [name, score] of scores) {
console.log(`${name}: ${score}`);
}
Output:
Karim: 90
Ayesha: 85
Rahul: 88
When Should You Use a Map?
Use a Map when you need to:
- Store key-value pairs.
- Use objects or other values as keys.
- Add, update, and remove entries frequently.
- Iterate over entries in insertion order.
- Track scores, product prices, or application settings.
What Is a Set in JavaScript?
A Set is a collection that stores unique values. If you add the same value more than once, the Set retains only one occurrence.
A Set can contain primitive values and objects. Its uniqueness rules use SameValueZero equality, which means, for example, that NaN is treated as equal to itself for Set membership.
Creating a Set
const numbers = new Set([10, 20, 30, 20, 10]);
console.log(numbers);
Output:
Set(3) { 10, 20, 30 }
The duplicate values are removed automatically.
Adding Values to a Set
Use add() to insert values.
const languages = new Set();
languages.add("JavaScript");
languages.add("Python");
languages.add("Java");
console.log(languages.size);
Output:
3
Adding a value that already exists does not increase the size.
languages.add("JavaScript");
console.log(languages.size);
Output:
3
Checking and Removing Values
Use has() to check membership and delete() to remove a value.
const colors = new Set(["Red", "Green", "Blue"]);
console.log(colors.has("Green"));
colors.delete("Green");
console.log(colors.has("Green"));
Output:
true
false
Use clear() when you want to remove all values from the Set.
Removing Duplicate Values From an Array
One common use of Set is to remove duplicates from an array.
const numbers = [1, 2, 2, 3, 3, 4, 4, 5];
const uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers);
Output:
[1, 2, 3, 4, 5]
The Set removes duplicate values, and the spread operator converts the collection back into an array.
Looping Through a Set
const courses = new Set([
"HTML",
"CSS",
"JavaScript"
]);
for (const course of courses) {
console.log(course);
}
Output:
HTML
CSS
JavaScript
Set values are visited in insertion order.
When Should You Use a Set?
Use a Set when you need to:
- Remove duplicates from a collection.
- Store unique user IDs or tags.
- Check whether a value has already been added.
- Maintain an ordered collection of unique values.
What Is a WeakMap in JavaScript?
A WeakMap stores key-value pairs like a regular Map, but it holds its keys weakly. Its keys must be objects or non-registered symbols that are eligible for weak collection.
A weak key does not keep an otherwise unreachable object alive merely because the key appears in the WeakMap. This makes WeakMap useful for associating additional information with objects without strongly retaining those objects.
Unlike Map, a WeakMap cannot be iterated over and does not have a size property.
Creating a WeakMap
const user = { name: "Karim" };
const userData = new WeakMap();
userData.set(user, {
role: "Developer",
active: true
});
console.log(userData.get(user));
Output:
{ role: 'Developer', active: true }
The object user is the key, and the associated object contains additional information.
Checking and Deleting WeakMap Entries
WeakMap supports methods such as set(), get(), has(), and delete().
const account = { id: 101 };
const accountData = new WeakMap();
accountData.set(account, "Active");
console.log(accountData.has(account));
console.log(accountData.get(account));
accountData.delete(account);
console.log(accountData.has(account));
Output:
true
Active
false
Using WeakMap for Private-Like Data
You can use a WeakMap to associate internal data with an object without placing that data directly on the object.
const privateData = new WeakMap();
function createUser(name) {
const user = { name };
privateData.set(user, {
accessLevel: "admin"
});
return user;
}
const user = createUser("Karim");
console.log(user.name);
console.log(privateData.get(user).accessLevel);
Output:
Karim
admin
The accessLevel value is stored separately from the user object.
This technique is useful for internal metadata and certain encapsulation patterns. It is not a complete security mechanism: code that can access privateData can still read its associated values.
Important WeakMap Limitations
WeakMap does not support:
- Iteration with
for...of. - A
sizeproperty. - A
clear()method. - Listing all keys or values.
These limitations are intentional because garbage collection can change which weakly held keys remain available.
What Is a WeakSet in JavaScript?
A WeakSet stores eligible object references and, in modern JavaScript, eligible non-registered symbols. Unlike a regular Set, it cannot store primitive values such as strings and numbers.
WeakSet holds its members weakly, so membership alone does not prevent an otherwise unreachable object from being garbage-collected.
Creating a WeakSet
const userOne = { name: "Karim" };
const userTwo = { name: "Ayesha" };
const users = new WeakSet();
users.add(userOne);
users.add(userTwo);
console.log(users.has(userOne));
console.log(users.has(userTwo));
Output:
true
true
The WeakSet tracks the object references.
Adding and Removing Objects
Use add() to add an eligible member and delete() to remove it.
const processedItems = new WeakSet();
const item = { id: 1 };
processedItems.add(item);
console.log(processedItems.has(item));
processedItems.delete(item);
console.log(processedItems.has(item));
Output:
true
false
Adding a primitive value such as a string throws a TypeError.
Practical Example: Tracking Processed Objects
A WeakSet can help an application determine whether a particular object has already been processed.
const processedUsers = new WeakSet();
function processUser(user) {
if (processedUsers.has(user)) {
console.log("User already processed.");
return;
}
processedUsers.add(user);
console.log(`Processing ${user.name}`);
}
const user = { name: "Karim" };
processUser(user);
processUser(user);
Output:
Processing Karim
User already processed.
The second call recognizes the same object reference and avoids processing it again.
This technique tracks object identity. If you create a new object with identical properties, the WeakSet treats it as a different object.
Important WeakSet Limitations
WeakSet does not support:
- Iteration using
for...of. - A
sizeproperty. - A
clear()method. - Retrieving or listing all members.
Use a regular Set if you need to count or enumerate the stored values.
Map vs Set vs WeakMap vs WeakSet
Although all four data structures store collections of information, they have different purposes.
| Feature | Map | Set | WeakMap | WeakSet |
|---|---|---|---|---|
| Main purpose | Store key-value pairs | Store unique values | Associate values with weak keys | Track weakly held members |
| Keys or members | Any value as a key | Any value as a member | Objects or eligible non-registered symbols as keys | Objects or eligible non-registered symbols as members |
| Strong references | Yes | Yes | Values are strongly held while entries exist; keys are weakly held | Members are weakly held |
| Iterable | Yes | Yes | No | No |
size property | Yes | Yes | No | No |
| Common use | Lookup tables | Unique collections | Object-associated metadata | Tracking object processing |
Which Data Structure Should You Choose?
Use Map when you need to associate keys with values and iterate through the entries.
Use Set when you need to store unique values or remove duplicate items from a collection.
Use WeakMap when you need to associate information with objects without keeping those key objects alive solely through the collection.
Use WeakSet when you need to track whether objects have been seen, processed, or registered without strongly retaining them.
Common Mistakes When Using Modern Data Structures
Expecting Map to Remove Duplicate Values
A Map prevents duplicate keys, not duplicate values.
const map = new Map();
map.set("first", 100);
map.set("second", 100);
console.log(map.size);
Output:
2
Both entries remain because their keys are different.
Expecting Set to Compare Objects by Their Contents
Set compares objects by reference identity rather than by their properties.
const items = new Set();
items.add({ id: 1 });
items.add({ id: 1 });
console.log(items.size);
Output:
2
The two object literals create different objects.
Trying to Iterate Over a WeakMap or WeakSet
This does not work:
const data = new WeakMap();
for (const item of data) {
console.log(item);
}
A WeakMap is not iterable. Use a regular Map when you need to loop through entries.
Assuming Weak Collections Immediately Remove Objects
Garbage collection timing is controlled by the JavaScript runtime. You should not expect a WeakMap entry or WeakSet membership to disappear immediately after an object becomes unreachable.
Weak collections are designed for memory management patterns, not for predictable cleanup timing.
Frequently Asked Questions
What is the main difference between Map and Set?
Map stores key-value pairs, while Set stores unique values. Choose Map when you need to look up values by keys and Set when you need a collection of unique items.
What is the difference between Map and WeakMap?
Map strongly retains its keys and supports iteration. WeakMap holds eligible keys weakly and does not support iteration or a size property.
What is the difference between Set and WeakSet?
Set can contain primitive values and objects, supports iteration, and provides a size property. WeakSet is limited to eligible objects and symbols and does not provide enumeration or a size.
Can a Map have duplicate keys?
No. Each Map key is unique. Setting an existing key updates its associated value instead of adding another entry.
Can a Set contain objects?
Yes. A Set can contain objects, but two different object references are treated as different members even if they have identical properties.
When should I use WeakMap instead of Map?
Use WeakMap when you need to associate data with object keys without strongly retaining those keys and you do not need to enumerate the entries.
Are WeakMap and WeakSet always better for memory management?
No. Weak collections are useful for specific reference-tracking patterns, but they are not automatically better for every application. Use Map or Set when you need predictable enumeration, collection size, or strong retention of the stored data.
Conclusion
JavaScript provides four useful modern data structures for different programming needs.
- Map stores key-value pairs and supports iteration.
- Set stores unique values and helps eliminate duplicates.
- WeakMap associates data with eligible weak keys without strongly retaining those keys.
- WeakSet tracks eligible object references without strongly retaining its members.
Choosing the right data structure helps you manage application data more clearly and avoid unnecessary work. As you build larger JavaScript applications, understanding the differences between these collections will help you write more maintainable code.