# Map and Set in JavaScript

## 1\. **Map and Set in JavaScript**

an interactive visual explainer covering **Map**, **Set**, the problems they solve, and how they compare to traditional objects and arrays. Click through each section to explore.

![](https://cdn.hashnode.com/uploads/covers/69a9156c3b896f7ad6a3c64f/e3554bb9-cc8c-48bc-afae-c7ddf9bf72a9.png align="center")

The widget above is fully interactive — click the tabs to switch between Map, Set, and the comparison view.

What Map solves. A plain JavaScript object coerces every key to a string, so using an object as a key silently becomes `"[object Object]"`. `Map` sidesteps this entirely by accepting any value as a key — objects, numbers, functions, or primitives — while also preserving insertion order and exposing a reliable `.size` property.

What Set solves. Arrays have no concept of uniqueness, so deduplication requires manual filtering and membership checks via `.includes()` scan the entire array. A `Set` enforces uniqueness automatically, and `.has()` runs in constant time regardless of how many elements the set contains.

The practical rule of thumb is to reach for `Map` whenever you need a key-value store where the keys are not plain strings, and to reach for `Set` whenever you need a collection where each element must appear exactly once.

* * *

## 2\. What Set is

The problem with arrays and objects

Arrays don't enforce uniqueness — `[1, 1, 2, 2]` is perfectly valid. To deduplicate, you'd manually loop or use filters. Objects work as key-value stores, but keys are always strings (or Symbols), which is limiting. Map and Set were introduced in ES6 to solve exactly these gaps.

**1\. Set — a collection of unique values**

A `Set` stores values where every entry must be distinct. Adding a duplicate simply does nothing.

```javascript
const s = new Set([1, 2, 2, 3, 3]);
console.log(s); // Set {1, 2, 3}
```

![](https://cdn.hashnode.com/uploads/covers/69a9156c3b896f7ad6a3c64f/fdd190a7-f4ca-49a3-ab75-255bbff5cf0e.png align="center")

Key `Set` methods: `.add(v)`, `.has(v)`, `.delete(v)`, `.size`, and it's directly iterable. A common pattern is `[...new Set(arr)]` to deduplicate any array in one line.  
**2\. Map — key-value storage with any key type**

A `Map` is like an object, but keys can be *anything* — objects, arrays, functions, numbers. Insertion order is also preserved.

```javascript
const m = new Map();
const keyObj = { id: 1 };
m.set(keyObj, "user data");
m.set(42, "a number key");
m.get(keyObj); // "user data"
```

![](https://cdn.hashnode.com/uploads/covers/69a9156c3b896f7ad6a3c64f/a8d67cf8-3981-4943-8fcc-3be987da9c8c.png align="center")

Key `Map` methods: `.set(k, v)`, `.get(k)`, `.has(k)`, `.delete(k)`, `.size`. You can also iterate with `.forEach()` or `for...of` over `[key, value]` pairs.

**Quick comparison**

|  | `Set` | `Map` | Plain `{}` |
| --- | --- | --- | --- |
| Purpose | Unique values | Key → value | Key → value |
| Key types | — | Any | String / Symbol |
| Duplicates | Rejected | Keys must be unique | Keys must be unique |
| Order preserved | ✓ | ✓ | ✓ (modern JS) |
| Size property | `.size` | `.size` | `Object.keys().length` |

* * *

## 3\. Difference between Map and Object

Here's a thorough breakdown of every meaningful difference between `Map` and a plain `Object` in JavaScript.

![](https://cdn.hashnode.com/uploads/covers/69a9156c3b896f7ad6a3c64f/916e145f-847f-4a29-9654-6652651d3b34.png align="center")

Here are the key differences explained:

**Key types** — this is the biggest one. An `Object` always coerces keys to strings, so `obj[1]` and `obj["1"]` are literally the same key. A `Map` uses strict equality (`===`) and accepts anything — DOM nodes, functions, other objects — as keys.

```javascript
const map = new Map();
const key = { id: 42 };
map.set(key, "metadata");  // works
map.get({ id: 42 });       // undefined — different reference!
map.get(key);              // "metadata" — same reference ✓
```

Prototype pollution — a plain `Object` inherits keys from `Object.prototype` (`toString`, `constructor`, etc.). This can cause subtle bugs when checking `"hasOwnProperty" in obj`. A `Map` starts completely empty, no inherited keys.

Integer key sorting — `Object` sorts integer-like keys numerically before all others, which can silently break expected insertion order. `Map` never does this.

When to use each:

Use `Map` when you have non-string keys, need to frequently add/remove entries, need the exact count quickly via `.size`, or need to iterate key-value pairs directly.

Use a plain `Object` when your data is simple string-keyed config or records, you need JSON serialization (APIs, `localStorage`), or you're writing code that others will read — objects are more familiar to most developers.

```javascript
const obj = { name: "alice", age: 30 };
JSON.stringify(obj);  // '{"name":"alice","age":30}' ✓

const map = new Map([["name", "alice"]]);
JSON.stringify(map);  // '{}'  ← silently empty!
```

* * *

## 4\. difference between `Set` and `Array` in JavaScript.

Here's a breakdown of every meaningful difference between `Set` and `Array` in JavaScript.

![](https://cdn.hashnode.com/uploads/covers/69a9156c3b896f7ad6a3c64f/d37a6a32-92a5-44e5-a5ee-cea52c879d96.png align="center")

Here are the differences that matter most in practice:

Uniqueness vs duplicates — the fundamental split. `Set` enforces uniqueness by design; `.add()` on an existing value is a silent no-op. `Array` happily holds `[1, 1, 1]`.

Index access — `Array` is index-based, so you can do `arr[0]`, [`arr.at`](http://arr.at)`(-1)`, slicing, etc. `Set` has no concept of position — `set[0]` is always `undefined`. If you need "the first item", convert it first: `[...set][0]`.

Membership check — this is where `Set` shines for performance:

```javascript
const arr = [1, 2, 3, ...millions];
arr.includes(x);   // O(n) — checks every element

const set = new Set([1, 2, 3, ...millions]);
set.has(x);        // O(1) — instant hash lookup
```

For large collections where you frequently check "is this value present?", `Set` is dramatically faster.

Array methods — `Set` has no `.map()`, `.filter()`, or `.reduce()`. You either spread it first or use `.forEach()`. This is the main friction point:

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

// Must convert to use array methods
const doubled = [...set].map(x => x * 2);  // [2, 4, 6, 8]
```

The deduplication trick — the most common real-world use of `Set` is as a quick dedup tool:

```javascript
const tags = ["js", "css", "js", "html", "css"];
const unique = [...new Set(tags)];  // ["js", "css", "html"]
```

Rule of thumb: reach for `Array` by default. Switch to `Set` when you need uniqueness guaranteed, or when you're doing heavy membership checks on large data.

* * *

## 5\. When to use Map and Set

![](https://cdn.hashnode.com/uploads/covers/69a9156c3b896f7ad6a3c64f/916c59ad-44e9-4336-b6d1-8b90f0b6c666.png align="center")

Here's the thinking behind each:

Reach for `Map` when you need key → value association. The clearest signal is memoization — storing the result of an expensive function call keyed by its input:

```javascript
const cache = new Map();
function expensiveCalc(n) {
  if (cache.has(n)) return cache.get(n);
  const result = /* heavy work */;
  cache.set(n, result);
  return result;
}
```

Also use `Map` when counting frequencies — it's cleaner than an object because you don't worry about prototype keys colliding with your data:

```javascript
const freq = new Map();
for (const word of words) {
  freq.set(word, (freq.get(word) ?? 0) + 1);
}
```

Reach for `Set` when you only care about existence, not association. The most common pattern is tracking what you've already seen — perfect for graph traversal or avoiding repeat processing:

```javascript
const visited = new Set();
function dfs(node) {
  if (visited.has(node)) return;
  visited.add(node);
  node.neighbors.forEach(dfs);
}
```

The other killer use case is the one-liner dedup: `[...new Set(arr)]` — converts an array to unique values and back in a single expression.

**The mental checklist:**

*   Do I need to associate a value *with* each item? → `Map`
    
*   Do I just need to know if an item *exists*? → `Set`
    
*   Do I need index access or rich methods like `.map()`/`.filter()`? → `Array`
    
*   Do I need simple string-keyed config that goes through JSON? → plain `Object`
    
    * * *
