---
title: "05 — Data Structures — Arrays, Maps, Sets, and the Built-In Toolbox"
uid: data-structures
tags: ["typed-arrays", "map", "built-in-objects", "arrays", "json", "set", "roadmap:javascript", "weakmap", "javascript"]
excerpt: "JavaScript ships a small toolbox of collection types — indexed sequences, keyed lookups, unique values, raw bytes — each purpose-built for a different shape of data."
date: 2026-08-13T03:28:07+0000
source: https://www.aveshina.my.id/en/blog/data-structures
---

"Arrays and objects, mostly" was my data-structures summary, and it undersold the toolbox. The idea that everything else hangs off: **JavaScript ships a small toolbox of collection types, and each one is purpose-built for a different *shape* of data — indexed sequences, keyed lookups, unique values, or raw bytes.** [1]

The framing that finally landed is grouping by *shape*, not by name. Once I stopped treating "array vs object" as the only choice, the right structure for a job became obvious:

```figure
<svg viewBox="0 0 740 260" xmlns="http://www.w3.org/2000/svg" class="my-6 w-full max-w-2xl" role="img" aria-label="Four shapes of collections: Indexed (Array) for ordered position-based access; Keyed (Map, Set, WeakMap, WeakSet) for lookups and uniqueness; Binary (TypedArray) for raw bytes; Serial (JSON) for transport.">
  <g font-family="ui-sans-serif, system-ui, sans-serif" text-rendering="geometricPrecision">
    <!-- Indexed -->
    <rect x="20" y="30" width="165" height="200" rx="10" fill="#e0e7ff" stroke="#6366f1" stroke-width="1.5"/>
    <text x="102" y="55" font-size="12" font-weight="700" fill="#1e1b4b" text-anchor="middle">Indexed</text>
    <text x="102" y="90" font-size="13" font-family="ui-monospace,monospace" fill="#1e1b4b" text-anchor="middle">Array</text>
    <text x="102" y="150" font-size="9.5" fill="#475569" text-anchor="middle">ordered</text>
    <text x="102" y="166" font-size="9.5" fill="#475569" text-anchor="middle">position access</text>
    <text x="102" y="200" font-size="9.5" font-style="italic" fill="#64748b" text-anchor="middle">map / filter / reduce</text>

    <!-- Keyed -->
    <rect x="200" y="30" width="165" height="200" rx="10" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
    <text x="282" y="55" font-size="12" font-weight="700" fill="#052e16" text-anchor="middle">Keyed</text>
    <g font-size="11" font-family="ui-monospace,monospace" fill="#052e16" text-anchor="middle">
      <text x="282" y="85">Map</text>
      <text x="282" y="105">Set</text>
      <text x="282" y="125">WeakMap</text>
      <text x="282" y="145">WeakSet</text>
    </g>
    <text x="282" y="195" font-size="9.5" font-style="italic" fill="#64748b" text-anchor="middle">lookup · uniqueness</text>

    <!-- Binary -->
    <rect x="380" y="30" width="165" height="200" rx="10" fill="#fce7f3" stroke="#db2777" stroke-width="1.5"/>
    <text x="462" y="55" font-size="12" font-weight="700" fill="#500724" text-anchor="middle">Binary</text>
    <text x="462" y="90" font-size="12" font-family="ui-monospace,monospace" fill="#500724" text-anchor="middle">TypedArray</text>
    <text x="462" y="110" font-size="12" font-family="ui-monospace,monospace" fill="#500724" text-anchor="middle">ArrayBuffer</text>
    <text x="462" y="150" font-size="9.5" fill="#475569" text-anchor="middle">fixed-type</text>
    <text x="462" y="166" font-size="9.5" fill="#475569" text-anchor="middle">raw bytes</text>
    <text x="462" y="200" font-size="9.5" font-style="italic" fill="#64748b" text-anchor="middle">WebGL · audio · files</text>

    <!-- Serial -->
    <rect x="560" y="30" width="165" height="200" rx="10" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.5"/>
    <text x="642" y="55" font-size="12" font-weight="700" fill="#422006" text-anchor="middle">Serial</text>
    <text x="642" y="90" font-size="13" font-family="ui-monospace,monospace" fill="#422006" text-anchor="middle">JSON</text>
    <text x="642" y="150" font-size="9.5" fill="#475569" text-anchor="middle">text format</text>
    <text x="642" y="166" font-size="9.5" fill="#475569" text-anchor="middle">transport</text>
    <text x="642" y="200" font-size="9.5" font-style="italic" fill="#64748b" text-anchor="middle">APIs · config</text>
  </g>
</svg>
```

## Indexed collections: the array

The array is the workhorse — an ordered, dynamically-sized, indexed collection [2]. It holds any mix of types, grows and shrinks on demand, and ships a rich method set: push/pop (stack), shift/unshift (queue), and the functional trio map, filter, reduce for transformation without mutation.

```
const nums = [1, 2, 3, 4];
const doubled = nums.map(n => n * 2);        // [2, 4, 6, 8]
const evens   = nums.filter(n => n % 2 === 0); // [2, 4]
const sum     = nums.reduce((a, b) => a + b, 0); // 10
```

That trio is the part I reach for daily. map transforms each element, filter keeps the ones that pass a test, reduce collapses the array into a single value. They compose — chaining filter().map() reads top-to-bottom and replaces most hand-written loops.

## Keyed collections: Map, Set, and the Weak variants

When the key isn't a sequential integer, plain objects used to be the only answer — but objects have limits: keys are coerced to strings, insertion order isn't always preserved, and there's no easy way to ask "how many keys?". The keyed collections fix all of that [3][4].

- **Map** — key-value pairs where keys can be *any* type (including objects and functions). Remembers insertion order. map.set(k, v), map.get(k), map.has(k), map.size. Reach for Map when keys are dynamic or when you need ordered iteration.
- **Set** — a collection of *unique* values. The fastest way to dedupe: [...new Set(arr)]. Useful for membership checks (set.has(x) is O(1)) where arr.includes(x) is O(n).
- **WeakMap / WeakSet** — like Map/Set, but keys (WeakMap) or values (WeakSet) must be objects and are held *weakly*: when nothing else references the object, the garbage collector reclaims it and the entry disappears automatically [5]. The use case is associating extra data with an object without leaking it — private metadata, caches keyed by DOM nodes.

The "weak" part only matters for memory. If I want to attach a cache to a DOM element without keeping that element alive forever, a WeakMap keyed by the element is the right structure; a plain Map would pin it in memory and leak.

## Typed arrays: raw binary

Typed arrays are array-like views over a fixed-length, fixed-type block of raw bytes [6]. Each variant — Int8Array, Uint8Array, Float32Array, Float64Array, and more — represents one numeric size and format. They're not for general-purpose lists; they're for binary data: file contents, image pixels, audio samples, network packets. Anywhere data arrives as bytes (WebGL buffers, the Fetch API's arrayBuffer(), FileReader), typed arrays are the interface.

```
const bytes = new Uint8Array([72, 105]);  // two bytes
const view  = new DataView(bytes.buffer); // read multi-byte values at offsets
```

The key idea is the split between the **buffer** (the raw memory) and the **view** (how you read it). One buffer can be read through multiple views of different types — that's how binary file parsers work.

## JSON and the built-in objects

Two more pieces of the toolbox round out the common case.

**JSON** (JavaScript Object Notation) isn't a data structure — it's a *text format* for representing structured data [7]. It's the lingua franca of web APIs and config files. The interface is two functions: JSON.stringify(obj) turns a JS value into a JSON string, JSON.parse(str) turns it back. The asymmetry to remember: JSON only carries strings, numbers, booleans, null, arrays, and plain objects — functions, undefined, Symbol, Map, and dates don't survive a round trip (dates become strings, the rest vanish).

The **built-in objects** — Math, Date, JSON itself, RegExp, Promise, Error, and all the global constructors — are always available without imports [8]. They're the standard library, small but sufficient: Math.max, Date.now(), RegExp for patterns, Promise for async work, Error for failure. Knowing they exist is half the battle; the other half is not reinventing what they already do.

## How I use this

The decision tree is short. Ordered list of items → **Array**, and lean on map/filter/reduce. Key-value lookup with dynamic or non-string keys → **Map**. Need uniqueness or fast membership → **Set**. Attaching metadata to an object without leaking it → **WeakMap**. Raw bytes from a file, fetch, or canvas → **TypedArray**. Sending data over the wire → serialize to **JSON**. The wrong choice is almost always "reached for a plain object when a Map or Set was the right tool" — once I internalized that keyed collections exist, the code I wrote got noticeably shorter.

## References

[1] Mozilla, "Indexed collections," MDN Web Docs, 2024. [Online]. Available: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections)

[2] I. Kantor, "Arrays," The Modern JavaScript Tutorial, 2024. [Online]. Available: [https://javascript.info/array](https://javascript.info/array)

[3] Mozilla, "Keyed collections," MDN Web Docs, 2024. [Online]. Available: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Keyed_collections](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Keyed_collections)

[4] LogRocket, "ES6 keyed collections — Maps and sets," 2022. [Online]. Available: [https://blog.logrocket.com/es6-keyed-collections-maps-and-sets/](https://blog.logrocket.com/es6-keyed-collections-maps-and-sets/)

[5] I. Kantor, "WeakMap and WeakSet," The Modern JavaScript Tutorial, 2024. [Online]. Available: [https://javascript.info/weakmap-weakset](https://javascript.info/weakmap-weakset)

[6] Mozilla, "JavaScript typed arrays," MDN Web Docs, 2024. [Online]. Available: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays)

[7] Mozilla, "Working with JSON," MDN Web Docs, 2024. [Online]. Available: [https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON)

[8] Mozilla, "Standard built-in objects," MDN Web Docs, 2024. [Online]. Available: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)

```quiz
Q: What's the fastest way to dedupe an array in modern JavaScript?
- arr.filter((x, i) => arr.indexOf(x) === i)
- [...new Set(arr)]
correct: 1
explain: A Set only stores unique values, so wrapping the array in new Set() and spreading it back out dedupes in one expression. Set.has() is also O(1), versus indexOf's O(n).

Q: When should you prefer a Map over a plain object?
- When keys are non-string (objects, functions) or dynamic, insertion order matters, or you need a clean .size
- Whenever you want better performance for any lookup
correct: 0
explain: Maps accept any key type, preserve insertion order, and expose .size. Plain objects coerce keys to strings and have inherited properties that can interfere. For simple string-keyed config, objects are fine.

Q: Why does a WeakMap not prevent garbage collection of its keys?
- Its keys are held weakly; when nothing else references the key object, the GC reclaims it and the entry vanishes automatically
- WeakMap entries expire on a timer
correct: 0
explain: WeakMap (and WeakSet) hold weak references to their keys/values. Once the key object is unreachable from anywhere else, the entry is eligible for collection — useful for attaching metadata without leaking.

Q: What does JSON.stringify drop during serialization?
- Numbers and booleans
- Functions, undefined, Symbol, Map, Set — and Date becomes a string
correct: 1
explain: JSON only encodes strings, numbers, booleans, null, arrays, and plain objects. Functions, undefined, Symbol, and Map/Set are omitted; Date is converted to an ISO string. Plan for this at the boundary.

Q: A typed array is best described as…
- a view of fixed type over a fixed-length block of raw bytes (an ArrayBuffer)
- a faster, immutable version of a regular Array
correct: 0
explain: Typed arrays (Uint8Array, Float32Array, …) are views over an ArrayBuffer, giving typed access to raw binary. They're for binary data (files, pixels, audio), not a general-purpose array replacement.
```
