Skip to main content

Command Palette

Search for a command to run...

Map and Set in JavaScript: The Data Structures You Are Underusing

Updated
8 min read
Map and Set in JavaScript: The Data Structures You Are Underusing

Most JavaScript developers learn two data structures early on — objects for key-value storage and arrays for lists. They work great. You use them everywhere. And then, at some point, you hit a problem that objects and arrays solve awkwardly — and you wonder if there is a better tool.

There is. It is called Map and Set.

These two data structures were introduced in ES6 and they do not get nearly enough attention. Once you understand what they are built for, you will start reaching for them naturally — and your code will be cleaner for it.


The Problem With Plain Objects

Objects seem perfect for key-value storage at first:

const user = {
  name: "Nawazish",
  age: 21,
  role: "developer"
};

Clean. Simple. But objects have some real limitations that show up as your code grows.

Keys are always strings (or symbols). If you try to use a number or an object as a key, JavaScript silently converts it to a string:

const obj = {};
obj[1] = "one";
obj[2] = "two";

console.log(Object.keys(obj)); // ["1", "2"] — numbers became strings

Objects inherit from a prototype. That means they come with built-in properties like toString, hasOwnProperty, and constructor. If you are not careful, iterating over an object can give you unexpected results.

No built-in size property. Want to know how many keys an object has? You have to write Object.keys(obj).length. Annoying.

Order is not guaranteed for all keys. Integer-like keys get sorted. String keys follow insertion order. It is inconsistent.

These are small frustrations individually. Combined, they make objects the wrong tool for certain jobs. That is where Map comes in.


What Is a Map?

A Map is a collection of key-value pairs — just like an object — but with none of the limitations above.

const map = new Map();

map.set("name", "Nawazish");
map.set("age", 21);
map.set("role", "developer");

console.log(map.get("name")); // "Nawazish"
console.log(map.size);        // 3

Simple. Clean. And far more powerful than it looks.


Map Key-Value Storage — The Visual

Map

┌─────────────────────────────────┐
│  Key          │  Value          │
├───────────────┼─────────────────┤
│  "name"       │  "Nawazish"     │
│  "age"        │  21             │
│  "role"       │  "developer"    │
│  { id: 1 }    │  "object key!"  │
│  42           │  "number key!"  │
└───────────────┴─────────────────┘

Any type can be a key. Numbers stay numbers. Objects stay objects. The insertion order is always preserved.


Map Methods You Need to Know

const map = new Map();

// Add entries
map.set("language", "JavaScript");
map.set("year", 2026);

// Read a value
map.get("language"); // "JavaScript"

// Check if a key exists
map.has("year");     // true
map.has("framework"); // false

// Delete an entry
map.delete("year");

// Get the size
map.size; // 1

// Clear everything
map.clear();

// Loop through entries
map.set("a", 1);
map.set("b", 2);
map.set("c", 3);

for (let [key, value] of map) {
  console.log(`\({key} → \){value}`);
}
// a → 1
// b → 2
// c → 3

Map vs Object — Side by Side

Object Map
Key types String or Symbol only Any type — numbers, objects, functions
Default keys Has inherited prototype keys No default keys
Size Manual — Object.keys().length Built-in — .size
Iteration Needs Object.entries() Directly iterable with for...of
Key order Inconsistent for integer keys Always insertion order
Performance Slower for frequent add/delete Optimized for frequent mutations
Best for Static config, structured records Dynamic key-value collections

The rule of thumb: if you are storing structured data with known, fixed keys — use an object. If you are building a dynamic collection where keys change, grow, or need to be non-strings — use a Map.


The Problem With Plain Arrays

Arrays are great for ordered lists. But one thing they handle poorly is uniqueness.

If you want to store a collection where every value appears only once, arrays make you do the work manually:

const arr = [1, 2, 3, 2, 1, 4];

// Remove duplicates the hard way
const unique = arr.filter((item, index) => arr.indexOf(item) === index);
console.log(unique); // [1, 2, 3, 4]

It works, but it is not elegant. And checking whether a value exists in an array uses includes() or indexOf(), which scans the entire array every time — slow on large collections.

That is where Set comes in.


What Is a Set?

A Set is a collection of unique values. Duplicates are automatically ignored. Looking up a value is fast. The order of insertion is preserved.

const set = new Set();

set.add(1);
set.add(2);
set.add(3);
set.add(2); // duplicate — silently ignored
set.add(1); // duplicate — silently ignored

console.log(set);      // Set { 1, 2, 3 }
console.log(set.size); // 3

No manual deduplication. No extra logic. You just add values and the Set handles uniqueness for you.


Set Uniqueness — The Visual

Adding values to a Set:

add(1) → { 1 }
add(2) → { 1, 2 }
add(3) → { 1, 2, 3 }
add(2) → { 1, 2, 3 }  ← duplicate, ignored
add(1) → { 1, 2, 3 }  ← duplicate, ignored
add(4) → { 1, 2, 3, 4 }

Final Set: { 1, 2, 3, 4 }

Set Methods You Need to Know

const set = new Set([1, 2, 3, 4, 5]);

// Check if value exists
set.has(3);  // true
set.has(10); // false

// Add a value
set.add(6);

// Delete a value
set.delete(1);

// Get the size
set.size; // 5

// Loop through values
for (let value of set) {
  console.log(value);
}
// 2, 3, 4, 5, 6

// Convert back to array
const arr = [...set];
console.log(arr); // [2, 3, 4, 5, 6]

The Most Common Set Use Case — Removing Duplicates

const numbers = [1, 2, 2, 3, 4, 4, 4, 5];

const unique = [...new Set(numbers)];
console.log(unique); // [1, 2, 3, 4, 5]

One line. That is it. This is probably the most used Set pattern in real JavaScript code.

Works with strings too:

const tags = ["js", "css", "js", "html", "css", "js"];
const uniqueTags = [...new Set(tags)];
console.log(uniqueTags); // ["js", "css", "html"]

Set vs Array — Side by Side

Array Set
Duplicates Allowed Not allowed — auto-removed
Check existence includes() — O(n) scan has() — O(1) lookup
Size .length .size
Index access Yes — arr[0] No — not index-based
Best for Ordered lists, position matters Unique collections, fast lookups
Remove duplicates Manual filter logic Automatic

When to Use Map and Set

Use Map when:

  • Your keys are not strings — numbers, objects, or other values as keys

  • You need to know the size quickly without extra code

  • You are frequently adding and removing entries

  • You need guaranteed insertion order for all key types

  • You are building a cache, a frequency counter, or a lookup table

Use Set when:

  • You need a collection of unique values

  • You want to remove duplicates from an array

  • You need fast existence checks — has() is much faster than includes() on large collections

  • You are tracking which items have been visited or processed


Real World Example — Frequency Counter with Map

function charFrequency(str) {
  const map = new Map();

  for (let char of str) {
    map.set(char, (map.get(char) || 0) + 1);
  }

  return map;
}

console.log(charFrequency("javascript"));
// Map { j→1, a→3, v→1, s→1, c→1, r→1, i→1, p→1, t→1 }

Real World Example — Track Visited Pages with Set

const visited = new Set();

function visitPage(url) {
  if (visited.has(url)) {
    console.log(`Already visited: ${url}`);
    return;
  }
  visited.add(url);
  console.log(`Visiting: ${url}`);
}

visitPage("nawazish.hashnode.dev");  // Visiting
visitPage("nawazish.hashnode.dev");  // Already visited
visitPage("nawazishkhan.in");        // Visiting

Key Takeaways

  • Map is key-value storage like an object, but accepts any key type, has a built-in .size, and is always insertion-ordered

  • Set is a collection of unique values — duplicates are automatically ignored

  • Use Map over objects when keys are dynamic, non-string, or the collection changes frequently

  • Use Set over arrays when uniqueness matters or you need fast existence checks with .has()

  • The one-liner to remove array duplicates: [...new Set(array)]

  • Both Map and Set are directly iterable with for...of


Objects and arrays will always be your bread and butter in JavaScript. But Map and Set exist for the cases where objects and arrays start showing their limits. Learn them, reach for them at the right moments, and your code will thank you.

If this helped, drop a reaction. I am writing through the full JavaScript fundamentals series publicly at nawazish.hashnode.dev — follow along if you are on the same path.