Pure function in JavaScript: same input, same output, no effects

A pure function always returns the same result for the same arguments and changes nothing outside itself. Two conditions, many benefits.
3 min read
Believemy logo

Some functions behave like a spreadsheet formula: give them the same inputs and they always hand back the same output, while nothing else in the program moves.

Those functions are called pure. They can be tested without setup, read without context, and moved from one file to another without surprises.


Definition

A pure function satisfies two conditions at once. It always returns the same result for the same arguments, and it produces no Side effect, meaning no change outside itself.

JAVASCRIPT
function grossTotal(net, rate) {
  return net * (1 + rate);
}

console.log(grossTotal(100, 0.2)); // 120
console.log(grossTotal(100, 0.2)); // 120, always

let discount = 0.1;
function impureTotal(net) {
  return net * (1 - discount); // depends on an outside variable
}

console.log(impureTotal(100)); // 90
discount = 0.5;
console.log(impureTotal(100)); // 50, same call, different result

The second function is not wrong, it is simply unpredictable in isolation: its result depends on a value that appears nowhere in its call.


The second trap: modifying its arguments

A function can return the right value and still be impure, because it changed what it was handed along the way.

JAVASCRIPT
function addImpure(list, item) {
  list.push(item); // modifies the argument it received
  return list;
}

function addPure(list, item) {
  return [...list, item];
}

const cart = ["keyboard"];
addPure(cart, "mouse");
console.log(cart.length); // 1, the original is intact

addImpure(cart, "mouse");
console.log(cart.length); // 2

The pure version produces a new list with Spread (...). That is the principle of Immutability, applied at the scale of a single function.


The impurities that hide

  • Math.random() and Date.now(): two identical calls, two results. Pass the value as an argument.
  • Reading an outside variable: the result depends on state invisible from the call.
  • Modifying a received object: the caller ends up with data it never changed.
  • Writing to a log or to storage: even without changing the result, it is an effect.
Good to know

A pure function is memoizable by construction: since the result depends only on the arguments, the cache cannot be wrong. See Memoization.


Frequently asked questions

Question

Can a whole program be pure?

No, and that is not the goal. A program that writes nothing, displays nothing and calls no service is useless. The aim is to gather the effects at the edge of the code and keep everything that computes pure, which is often most of an application.


Question

Can a pure function call another function?

Yes, provided that one is pure as well. Purity propagates: a function that only calls pure functions and touches nothing outside stays pure. A single impure call in the chain, however, is enough to contaminate the whole thing.


Question

What is the concrete benefit for tests?

A test on a pure function fits on one line: call it with values, compare the return. No database to prepare, no service to fake, no cleanup afterward. That is why a Unit test on impure code is almost always longer to write than to make pass.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.