JavaScript ES2024 ·
✓ verified by execution on 2026-08-16
A pure function always evaluates to the same result value given the same argument values and has no observable side effects.
The Anatomy of Purity
To understand why purity matters, you first need to consider what happens when a program runs. Every application relies on some form of state—data stored in memory, databases, or the user interface. When code behaves unpredictably, it is almost always because the state changed when you did not expect it to.
If you pass the same arguments to a pure function, you will always get the exact same answer back. It does not depend on anything that changes over time, like Math.random(). It does not secretly rely on a variable declared elsewhere in your file. It acts as an isolated, mathematical box.
javascript
function add(a, b) { return a + b;}console.log(add(2, 3));console.log(add(2, 3));
Output
5
5
Your output
If a function uses randomness, it returns a different value each time. That unpredictability makes it impure.
Predict the outputjavascript
Read the code. What exactly will it print? Commit to an answer before you look.
A side effect is any state change that is observable outside the called function other than its return value. A function might return the correct value, but if it quietly modifies something else along the way, it is impure.
Consider a function that updates a global variable. A reader might expect the function merely to compute a value, but instead, it alters the program’s broader state. This creates hidden dependencies.
javascript · visualize
let total = 0;function addToTotal(amount) { total += amount; return total;}console.log(addToTotal(5));console.log(addToTotal(5));
Mutating an object argument is another common side effect. Because objects are passed by reference, any changes you make to properties on that object are instantly visible to the code that called your function. This can lead to horrifying bugs where data seems to change itself from a distance.
An impure function reaches outside itself and mutates shared memory, so its effect outlives the call and the same inputs no longer guarantee the same result.
javascript
function addAge(person) { person.age = 30; return person;}const user = { name: 'Alice' };addAge(user);console.log(user.age);
Output
30
Your output
Embracing Immutability
To avoid side effects when working with objects and arrays, you can use immutability. Instead of modifying an object, you create a brand new one. The spread syntax (...) allows you to copy all existing properties into a new object and overwrite just the ones you need to change.
Array methods like .map() and .filter() are fantastic for writing pure functions because they return a new array instead of modifying the original one.
Purity is stricter than it first looks in some places and looser in others.
Reading constants: Reading from an immutable global variable does not violate purity. If the variable never changes, the function remains entirely predictable.
Internal mutations: Internal mutations (like creating a local array inside the function, modifying it, and returning it) are completely fine as long as they don’t affect outer state. The caller never knows the difference.
A Note on React and Frameworks
If you are learning JavaScript to use a framework like React, you will hear a lot about pure functions. React relies heavily on functional purity for its components and state updates (for instance, treating props and state as immutable). However, it is important to remember that purity is a core computer science and vanilla JavaScript concept, not a React invention. React merely uses these same vanilla JS mechanics to figure out when to efficiently redraw the screen.
Check yourself
Does calling `console.log` inside a function violate its purity?
Reveal answer
Using console.log doesn't affect purity because it doesn't change variables. — console.log writes to the standard output stream, which is an observable side effect. Therefore, a function calling console.log is technically impure.
If a function does not accept any arguments, is it automatically considered pure?
Reveal answer
No, because it must rely on global state or randomness to produce varying results. — Functions without arguments often rely on global variables or randomness (like Date.now()), making them impure.
Is it acceptable for a pure function to modify an array passed to it, provided it returns the correct mathematical result?
Reveal answer
Only if the array contains numbers. — Modifying an argument (like pushing to an array or mutating an object property) affects the caller's state, which is a side effect.
When copying an object to avoid mutations, does spread syntax (`...`) completely isolate all nested properties?
Reveal answer
Yes, it creates a full, deep clone of the object. — They only make shallow copies. Nested objects are still passed by reference and mutating them inside a function is a side effect.
Challenges
🐞 Bug Hunt+20 XP
The function `addItem` currently modifies the original `cart` array, making it impure. Refactor it into a pure function that returns a new array with the new item added, leaving the original array unchanged.
This code runs. It just does the wrong thing. Read it, find the defect,
fix it — the tests below decide when you are right.
javascript
Test 1 — expects "Pure!"
Need a hint? (−25% XP)
Use the spread operator `[...array]` to create a copy of the array instead of using `.push()`.