Toggle theme D

JavaScript developers live in objects and arrays. They handle most tasks well, but they're not the only tools available. Map and Set are two data structures built into JavaScript that solve problems objects and arrays handle awkwardly.

What Map Is

Map is a collection of key-value pairs, like an object. But unlike objects, Map accepts any type of key — strings, numbers, objects, functions, anything.

const userRoles = new Map();

userRoles.set('alice', 'admin');
userRoles.set('bob', 'editor');
userRoles.set('charlie', 'viewer');

console.log(userRoles.get('alice'));   // 'admin'
console.log(userRoles.has('bob'));     // true
console.log(userRoles.size);           // 3

The API is clean. .set() to add, .get() to retrieve, .has() to check existence, .size for count. No surprises about which method to use.

What Set Is

Set is a collection of unique values. Add a duplicate and it gets ignored — no error, no exception, just silently ignored.

const tags = new Set();

tags.add('javascript');
tags.add('nodejs');
tags.add('javascript');  // ignored — already exists

console.log(tags.has('nodejs'));  // true
console.log(tags.size);           // 2

The uniqueness guarantee is built in. You don't need to check if something exists before adding it. Sets just handle that for you.

Why Objects Fall Short as Maps

Here's a problem with using plain objects for key-value storage: string coercion.

const map = {};

map[1] = 'one';
map['1'] = 'string one';

console.log(map[1]);      // 'string one'
console.log(map['1']);    // 'string one'

The keys 1 and '1' are coerced to the same string, so the second assignment overwrites the first. With Map, numeric keys stay numeric:

const map = new Map();

map.set(1, 'one');
map.set('1', 'string one');

console.log(map.get(1));      // 'one'
console.log(map.get('1'));    // 'string one'

Objects also have prototype pollution risks and non-integer keys don't iterate predictably. Map sidesteps both — it has no prototype by default, and iteration follows insertion order.

Why Arrays Aren't Great for Unique Collections

Arrays let you add duplicates. If you need unique values, you're checking manually:

const items = ['a', 'b', 'a', 'c', 'b'];

// Getting unique values
const unique = items.filter((item, index) => items.indexOf(item) === index);
// or
const unique = [...new Set(items)];

console.log(unique); // ['a', 'b', 'c']

This works, but it's a workaround. If you know uniqueness matters from the start, Set is the right tool:

const unique = new Set(['a', 'b', 'a', 'c', 'b']);
console.log([...unique]); // ['a', 'b', 'c']

Sets also have O(1) lookup. Checking set.has(value) is fast regardless of size. For arrays, includes() scans the entire list.

Iteration and Methods

Map and Set are iterable, which means you can loop through them directly:

const fruitMap = new Map([
  ['apple', 5],
  ['banana', 3],
  ['mango', 2]
]);

for (const [fruit, count] of fruitMap) {
  console.log(`\({fruit}: \){count}`);
}
const colors = new Set(['red', 'green', 'blue']);

for (const color of colors) {
  console.log(color);
}

Both support .forEach() too, if you prefer that style.

When to Use Each

Use Map when:

  • You need key-value storage with non-string keys

  • You need predictable iteration order

  • You want a clean API without prototype pollution

Use Set when:

  • You need a collection of unique values

  • Fast membership checking matters

  • You're storing values that shouldn't repeat

Stick with objects when:

  • You're defining plain data structures with known properties

  • You're working with JSON serialization

  • The data is temporary or configuration-like

Stick with arrays when:

  • You need ordering with duplicates

  • You need indexed access by position

  • You're working with data that will serialize to JSON arrays

Wrapping Up

Map and Set aren't replacements for objects and arrays — they're complements. Map gives you flexible key-value storage with a clean API. Set gives you uniqueness guarantees without extra work. When you encounter a problem that objects or arrays handle awkwardly, reach for these. They'll make your code cleaner and your intent clearer.