JavaScript Map

The Map object is a powerful collection introduced in ES6 that allows you to store data in key-value pairs. While it might look similar to a standard JavaScript Object, Maps offer several specialized features that make them superior for specific programming tasks, such as maintaining insertion order or using non-string keys.

Key-Value Pairs:

  • Unique Keys: Each key in a Map is unique. If you try to add a duplicate key, the new value will simply overwrite the old one.
  • Flexible Key Types: Unlike regular Objects which primarily restrict keys to strings or symbols a Map allows keys of any data type. This includes functions, objects, and even other Maps.
Developer Tip: Use a Map when you need to associate data with an object without actually modifying that object. This is perfect for metadata or "weak" associations in complex applications.

Iterability:

  • Maps are built to be iterable by default.
  • They maintain the insertion order of elements. When you loop through a Map, the items appear in the exact order they were added.

Example: Creating a Map

You can initialize a Map empty or pass an array of arrays to the constructor to prepopulate it.

// Creating an empty map
const userSession = new Map();

// Adding entries using .set()
userSession.set('id', 101);
userSession.set('role', 'admin');

// Using an object as a key
const metadata = { version: "1.0" };
userSession.set(metadata, 'Active');
Common Mistake: Beginners often try to set Map values using the bracket notation like myMap['key'] = 'value'. While this "works" in JavaScript because a Map is technically an object, it doesn't actually add the data to the Map's internal collection. Always use .set().

Accessing Values:

  • Use the get() method to retrieve a value. If the key doesn't exist, it returns undefined.
  • Use the has() method to check for existence, which returns a boolean (true/false).
  • Use the delete() method to remove a specific entry by its key.

Example: Accessing Values

const myMap = new Map();
myMap.set('name', 'John');
myMap.set('age', 30);

console.log(myMap.get('name')); // Output: John
console.log(myMap.has('age'));  // Output: true

// Checking for a non-existent key
console.log(myMap.get('email')); // Output: undefined
Watch Out: When using objects as keys, remember that JavaScript compares objects by reference, not by value. Two different objects that look identical {} === {} are considered different keys in a Map.

Size:

  • The size property returns the current number of elements in the Map. Unlike Objects, where you have to manually count keys using Object.keys(obj).length, Maps provide this value instantly.

Example: Size

const products = new Map();
products.set('p1', 'Laptop');
products.set('p2', 'Mouse');

console.log(products.size); // Output: 2
Best Practice: Use the .size property instead of tracking a separate counter variable. It is highly optimized and always reflects the current state of your collection.

Iterating over a Map:

Maps provide several ways to traverse their content. Because they are iterable, they work perfectly with modern loop syntax.

  • forEach(): Similar to Array.forEach, it takes a callback.
  • for...of: The most readable way to loop through entries.
  • keys() / values(): Helpful when you only care about one side of the pair.

Example: Iterating over a Map

const fruitInventory = new Map([
  ['apples', 50],
  ['bananas', 20],
  ['oranges', 15]
]);

// Using for...of with destructuring
for (const [fruit, count] of fruitInventory) {
  console.log(`We have ${count} ${fruit} in stock.`);
}

// Using forEach
fruitInventory.forEach((value, key) => {
  console.log(`${key}: ${value}`);
});

Real-World Use Case: Frequency Counters

Suppose you are building a feature to count how many times words appear in a paragraph. A Map is ideal for this because it handles frequent updates to values efficiently.

const words = ['apple', 'pear', 'apple', 'orange', 'apple', 'pear'];
const counter = new Map();

words.forEach(word => {
  const currentCount = counter.get(word) || 0;
  counter.set(word, currentCount + 1);
});

console.log(counter.get('apple')); // Output: 3

 

Key Points

  • Versatility: JavaScript Maps are collections of key-value pairs where keys can be objects, functions, or primitives.
  • Order: Unlike standard Objects, Maps strictly maintain the order of insertion.
  • Performance: Maps generally perform better in scenarios involving frequent additions and removals of key-value pairs.
  • Built-in Helpers: Methods like clear(), has(), and the size property make data management much cleaner than using plain objects.