JavaScript Modern Data Structures: Map, Set, WeakMap, and WeakSet

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 size property.
  • 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 size property.
  • 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.

FeatureMapSetWeakMapWeakSet
Main purposeStore key-value pairsStore unique valuesAssociate values with weak keysTrack weakly held members
Keys or membersAny value as a keyAny value as a memberObjects or eligible non-registered symbols as keysObjects or eligible non-registered symbols as members
Strong referencesYesYesValues are strongly held while entries exist; keys are weakly heldMembers are weakly held
IterableYesYesNoNo
size propertyYesYesNoNo
Common useLookup tablesUnique collectionsObject-associated metadataTracking 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.