Overview

10 Dealing with collections

This chapter moves from objects to the broader world of JavaScript collections, showing how to model data and transform it idiomatically. It starts with arrays—the language’s most common collection—highlighting functional techniques that make code expressive and predictable. It then introduces Maps and Sets for key–value lookups and uniqueness, and closes by tackling mutability: when it hurts, how to prevent accidental changes, and how to write clear, maintainable updates to state without mutating it.

Arrays are presented as dynamic, object-like structures whose size and element types can change, with “holes” possible when writing past bounds or deleting elements. You learn creation patterns and core operations for adding and removing items at either end (push/pop, unshift/shift) and at arbitrary positions (delete, splice vs. the non-mutating slice). Iteration options range from classic for loops to for…of and entries, with caveats around forEach (no early exit, synchronous by design). The chapter leans into functional patterns: map and flatMap for one-to-one and one-to-many transformations; every and some for condition checks; find and filter for search and selection; locale-aware sorting via a compare function and non-mutating toSorted; and reduce for aggregations and building complex results. Throughout, it calls out performance implications (for example, shifting vs. popping, repeated includes vs. Sets).

Maps provide predictable key–value storage with any type as a key (including objects), stable insertion order, and clear APIs for set/get/has/delete/clear and iteration over entries/keys/values; identity, not shape, determines object-key equality. WeakMap mirrors Map but holds weak references to keys to help avoid memory leaks. Sets efficiently track distinct items, with fast membership checks, and now offer first-class set operations (union, intersection, difference, subset checks); WeakSet offers the same weak-referencing advantages as WeakMap. The chapter then motivates immutability (e.g., React state updates) and shows practical tools: using TypeScript’s read-only types (as const, ReadonlyArray/Map/Set) to guard against mutation at compile time, and applying Immer to express “mutations” against a draft Proxy that produces a new, updated state object under the hood (with support for Maps/Sets and a note on the performance trade-off).

Writing to an array index outside of array bounds expands the array.
The push and pop methods modify the end of an array, whereas shift and unshift modify the array’s beginning.
Deleting an item from an array creates a hole in the array.
The map function calls the provided callback function (f) on each array item, and creates a new array with callback return values.
The find function finds one item in an array: the first item for which the find callback returns true.
The filter function creates a new array that contains all items for which the callback returns true.
The reduce function applies a callback to an aggregated value and each item in an array to reduce the array to a single value.
A map is a collection of key-value pairs, where a key can be anything—even another object.

Summary

  • Arrays in JavaScript are dynamic and resize automatically when new items are added.
  • We can modify the contents of an array using several methods accessible from array objects:
    • The built-in push and pop methods add items to and remove items from the end of the array.
    • The built-in shift and unshift methods add items to and remove items from the beginning of the array.
    • The built-in splice method can be used to remove items from and add items to arbitrary array positions.
  • Arrays have several useful methods:
    • The map method creates a new array with the results of calling a callback on every element.
    • The every and some methods determine whether all or some array items satisfy a certain criterion.
    • The find and filter methods find array items that satisfy a certain condition.
    • The sort method sorts an array in-place.
    • The reduce method aggregates all items in an array into a single value.
  • Maps are collections of key-value pairs. Whereas objects can only use strings and symbols as keys, maps can use anything as a key.
  • Sets are collections of distinct items. They’re effectively maps with only keys, no values.
  • Mutability refers to the ability to modify (“mutate”) a collection. Immutable collections are often preferred to avoid bugs from unexpected mutations.
    • Objects, arrays, maps, and sets are all mutable, but you can make them effectively immutable using TypeScript’s read-only types.
    • Immer allows you to create a modified copy of an immutable collection by applying your changes to a “draft,” which works like a mutable version of that collection.

FAQ

How do you create arrays in JavaScript, and how are they different from typed-language arrays?Prefer array literals like [] (for example, ["Kuma","Hattori"]) over the Array constructor. The one niche for new Array(n) is preallocating length (often followed by .fill()). JavaScript arrays are dynamic and can hold mixed types; their size can grow or shrink, and each array is also an object.
What happens when I read or write outside an array’s current bounds?Reading an out-of-range index returns undefined (no exception). Writing to an out-of-range index expands the array and can create “holes” (empty slots) for skipped indices. The length property always reflects the highest index + 1. You can also manually adjust length to trim or expand with holes.
What’s the difference between push/pop, shift/unshift, and delete/splice/slice for modifying arrays?- push/pop add/remove at the end (fast).
- unshift/shift add/remove at the start (can be costly on large arrays due to item moves).
- delete array[i] leaves a hole and does not change length.
- splice(start, count, ...items) removes and/or inserts, shifting items to fill gaps—no holes.
- slice(start, end) returns a shallow copy of a subarray without changing the original; use [...array] or array.slice() to copy an entire array.
What’s the recommended way to iterate arrays, and what pitfalls should I avoid?- Use for...of to iterate values and array.entries() with destructuring for [index, value] pairs.
- Traditional for works too.
- forEach can’t be break’d or await’ed per iteration and always runs all items; prefer for...of for early-exit or async steps.
- Avoid for...in on arrays; it iterates indices and any enumerable object properties, which is rarely intended.
When should I use map vs flatMap, and how does flat help?Use map for 1:1 transforms (each input element produces exactly one output). Use flatMap when each input can yield zero, one, or many outputs; it combines map with a one-level flat in a single, optimized pass. If you ever find yourself writing array.map(...).flat(), consider flatMap.
How do every, some, find, and filter differ, and do they short-circuit?- every(fn) returns true only if all items pass; it short-circuits on the first failure or on empty arrays (true).
- some(fn) returns true if any item passes; it short-circuits on the first success.
- find(fn) returns the first matching element or undefined (short-circuits on first match).
- filter(fn) returns all matching elements in a new array (must scan all items).
Callbacks are coerced to boolean (truthy/falsy rules apply).
How does Array.sort work, how do I sort strings correctly, and how do I avoid mutating the original?sort(compare) reorders the array in place using a compare function that returns a negative/zero/positive number for a/b ordering. For locale-aware, Unicode-correct string sorting, use new Intl.Collator().compare(a,b) (faster than repeatedly calling localeCompare). To avoid mutating the source, use toSorted(compare) (ES2023) or copy first ([...array].sort(...)).
Why use Map instead of a plain object, and what should I know about WeakMap?Maps store only what you put in them, maintain insertion order, and let you use any type (including objects) as keys with identity-based equality (key1 === key2). Core ops: set, get, has, delete, size, and iteration over entries/keys/values. WeakMap holds weak references to object keys to prevent memory leaks; keys must be objects, it has no size, and it isn’t iterable—access by get(key) only.
When should I use Set, what new set operations exist, and how is WeakSet different?Use Set to track unique items with fast has lookups (O(1)), a better choice than repeatedly calling array.includes (O(n)). ES2024 adds union, intersection, difference, and isSubsetOf for concise, efficient set algebra. WeakSet stores only objects with weak references (no size, not iterable), helping avoid leaks when tracking object membership.
How can I keep collections immutable in React/TypeScript, and what does Immer provide?In React, don’t mutate state directly (e.g., avoid todos.push); create new arrays/objects (e.g., setTodos([...todos, newTodo])). In TypeScript, use as const, ReadonlyArray<T>, ReadonlyMap, and ReadonlySet to enforce non-mutation at compile time. For complex immutable updates, Immer’s produce lets you “mutate” a draft; it returns a new state with only the necessary structural copies. Enable its Map/Set support with enableMapSet().

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Secrets of the JavaScript Ninja, Third Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Secrets of the JavaScript Ninja, Third Edition ebook for free