liveBook · Manning

Immutable collection

As explained in The Joy of JavaScript

An object whose fields cannot be changed after creation and whose state is represented without in-place mutation.

An immutable collection keeps its existing state intact when a computation produces a result. Instead of changing an array or object in place, create a new result. This matters when another part of an application still holds the original reference: an unexpected change there can make later behavior hard to predict, especially around asynchronous work. section 4.1

In JavaScript, the choice depends on what kind of state you are handling:

  • For an array pipeline, use filter and map to derive results while leaving the original array intact; reduce can combine those results into a value. Do not substitute reverse or sort when the original order must survive: those methods mutate the array in place. section 4.1
  • For an object that represents a value, prevent its fields from being changed after creation. An operation such as adding two Money values returns a new Money value rather than changing either operand. section 4.5
  • For a changed object shape, spread syntax can copy an object's owned properties and override a field in a new object: `{ ...frog, name: 'Toad' }`. This is a shallow clone, not a general guarantee that everything reachable through the copy is immutable. section 3.4.3

A value that stays put

`const USD = Money('$'); USD(3).plus(USD(7)).equals(USD(10)); // true` treats the sum as another value. Assigning `USD(3).amount = 5` instead attempts to change what that value means; the frozen Money object rejects the assignment. Amount and currency together describe its identity. section 4.5

Immutability is also a rule for how functions advance application state: take the data they need as inputs, leave observable existing state unchanged, and return a new state. Combined with predictable results for the same inputs, this supports pure functions. It is a design choice, not a requirement that every domain object be frozen: mutable Block and Transaction objects can accommodate hash recalculation and extension, while Money is suited to value-object behavior. section 4.1.2 section 4.5

Listing 4.13 Details of the Money value object
const BTC = 'B|';
 
const Money = curry((currency, amount) =>
  compose(                                                 #1
    Object.seal,
    Object.freeze
  )(Object.assign(Object.create(null),                     #2
    {
      amount,
      currency,
      equals: other => currency === other.currency &&
          amount === other.amount,
      round: (precision = 2) => 
          Money(currency, precisionRound(amount, precision)),
      minus: m => Money(currency, amount - m.amount),
      plus: m => Money(currency, amount + m.amount),
      times: m => Money(currency, amount * m.amount),
      compareTo: other => amount - other.amount,
      asNegative: () => Money(currency, amount * -1),
      valueOf: () => precisionRound(amount, 2),            #3
      toString: () => `${currency}${amount}`            
    }
  ))
);
 
// Zero
Money.zero = (currency = BTC) => Money(currency, 0);       #4
 
// Static helper functions
Money.sum = (m1, m2) => m1.add(m2);
 
Money.subtract = (m1, m2) => m1.minus(m2);
 
Money.multiply = (m1, m2) => m1.times(m2);
 
function precisionRound(number, precision) {
  const factor = Math.pow(10, precision);
  return Math.round(number * factor) / factor;
}

The Money implementation freezes its constructed object and defines operations that construct another Money value. section 4.5

How The Joy of JavaScript covers it

How deep it goes
Shows array-operation contrasts and a frozen Money implementation, while treating immutable design as a choice rather than requiring it for every object.
Examples
Uses block validation with filter, map, and reduce, plus a frozen Money object whose arithmetic returns new values.
What it assumes
Assumes familiarity with JavaScript functions and array APIs; introduces the functional rules for creating new state.
What you can do after
Build it from scratch as a frozen Money-style value object, or apply array transformations without changing the original array.
How it connects
Connects immutability to pure functions, value objects, higher-order array functions, and object spread.

Also explained in

Compare how 24 books explain immutable collection →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Joy of JavaScript. The section links point to the parts of the book it draws on.