liveBook · Manning

Pure function

As explained in The Joy of JavaScript

A pure function is a function whose output is determined solely by its explicit inputs and whose evaluation has no externally observable side effects.

A pure function computes its result from its inputs and leaves externally observable state unchanged. Given the same inputs, it produces the same output. This predictability is called referential transparency: a call can be replaced by its result without changing the program’s behavior. section 4.1 section 4.1.2

Purity is more than returning a value. Reading shared state makes the result depend on something the caller did not supply; changing an object passed by the caller creates a side effect. Console output, filesystem access, network writes, and randomness also break the rule. A function may use values from a closure when the enclosing function follows the same purity rules. The aim is not to prohibit useful effects, but to keep them apart from the logic that transforms data. section 4.1.2 section 4.3.1

Make a dependency visible

Consider `assemble(keys)`, which joins properties read through `this`. Its result depends on an assumed calling context. Changing its signature to `assemble(keys, obj)` makes that dependency an argument: `keys.map(f => obj[f]).join('')`. Neither version needs to change the object, but the second is easier to reason about and compose because the required object is explicit. Local variables in a hash calculation are not themselves the problem; dependence on an implicit external context is. section 4.3.2

Pure functions fit together as a data flow: one function’s output becomes another’s input. Array `filter` and `map` can select and transform values while leaving the original array intact; a subsequent `reduce` produces a result. This avoids surprises when another part of an application still holds the original array. By contrast, in-place operations such as `reverse` and `sort` can change shared data. section 4.1 section 4.3

const computeBalance = address =>
 compose( 
   Money.round,
   reduce(Money.sum, Money.zero()),
   map(balanceOf(address)), 
   flatMap(prop('data')),
   filter( 
     compose( 
       not,
       prop('isGenesis')
     )
   ),
   Array.from
 );

The balance calculation is expressed as a composition: select ledger blocks, extract transactions, map them to balance changes, sum them, and round the result. section 4.2

Start a refactor by splitting a large operation into small tasks and examining each task’s inputs and effects. Hash generation, for example, separates assembling object data from computing its digest; currying supplies hash options before those operations are composed. The surrounding method can still know about its transaction object while the functions doing the calculation receive the data they need. Purity does not require abandoning objects. section 4.3.2 section 4.4.2 section 4.8

Real applications still read files and make requests. Put those operations at a boundary and compose them with pure transformations. A word-counting pipeline, for instance, reads a file, decodes it, splits its contents, and counts the words; reading is effectful, while the data-processing steps can remain separate. This division makes critical logic easier to test, reuse, and reason about without pretending the entire application is pure. section 4.3.1 section 4.8

How The Joy of JavaScript covers it

How deep it goes
Defines purity and referential transparency, then works through dependency exposure, decomposition, composition, and practical effect boundaries.
Examples
Uses array filtering and reduction, transaction hashing, wallet-balance calculation, and file word counting as concrete cases.
What it assumes
Assumes working JavaScript familiarity with functions and objects; develops functional-programming rules through concrete refactorings.
What you can do after
Practice/perform refactoring that exposes hidden dependencies, composes pure calculations, and isolates effectful work.
How it connects
Connects pure functions to immutability, side effects, referential transparency, higher-order functions, currying, and function composition.

Also explained in

Compare how 19 books explain pure function →

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.