Map vs WeakMap in practice

In JavaScript, both Map and WeakMap are used to store key-value pairs. While they have some similarities, they also have some important differences that make them suitable for different use cases. This article will explore their differences, similarities, and common uses.

Differences

An important difference between Map and WeakMap is the type of keys they support. Map keys can be any data type, including primitives such as strings and numbers. WeakMap keys, on the other hand, must be objects. If you try to use a primitive value as a WeakMap key, you will get a TypeError.

let weakMap = new WeakMap();
let obj = {};

weakMap.set(obj, "ok"); // it works (object key)
weakMap.set("test", "Not ok"); // error because "test" is not an object
WeakMap key as a string - error

Another difference is the way memory is managed. Map keys are not garbage collected; the values associated with those keys may continue to occupy memory even after they are no longer needed. In contrast, when using a WeakMap, the key-value pairs can be garbage collected when the keys are no longer reachable.

Similarities

Both Map and WeakMap provide a way to store key-value pairs. They also both have similar methods for setting and getting values. For example, with a Map, you can use the set method to set a value for a key, and the get method to retrieve a value for a key. With a WeakMap, you can use the set method to associate a value with a key, and the get method to retrieve the value for a key.

When to use what

Here are some common usages for Map:

  • Storing data with a one-to-one relationship between keys and values
  • Creating a dictionary of word counts for a given text
  • Storing and retrieving configuration options for a web application
  • Creating a cache for frequently accessed data
let text = "zażółć gęślą jaźń";
let wordCounts = new Map();
text.toLowerCase().split(" ").forEach(word => {
  const count = wordCounts.get(word) || 0;
  wordCounts.set(word, count + 1);
});
console.log(wordCounts); // Map(3) {'zażółć' => 1, 'gęślą' => 1, 'jaźń' => 1}
Map sample usage

And here are some common usages for WeakMap:

  • Storing private data associated with an object
  • Storing metadata about DOM elements that may be garbage collected
  • Storing temporary data associated with a function call
  • Storing data associated with an object that needs to be garbage collected to prevent memory leaks
let weakMap = new WeakMap();

let keyObj = {}; // Create an object to use as a key
weakMap.set(keyObj, "Hello, World!"); // Set a value in the WeakMap using the key object
let value = weakMap.get(keyObj);

console.log(value); // Output: Hello, World!

keyObj = null; // Delete the key object and its associated value from the WeakMap

// The key object and its value are now eligible for garbage collection

Conclusion

In summary, Map and WeakMap are both useful for storing key-value pairs, but they have some key differences that make them suitable for different use cases. By understanding the differences between Map and WeakMap, and their common uses, we can choose the best data structure for our specific needs.