Side effects
A side effect is any action of a function that changes state outside the function itself or depends on external state, instead of simply computing a result from its arguments. Side effects are what make code harder to test and to predict, which is why teams try to keep them in one clearly marked layer of the program.
Theory
TL;DR
- A side effect is any influence a function has on its environment, or any dependency on it, beyond the returned value.
- Classic examples:
console.log,alert, DOM mutation,fetch, writing to a global variable, file access. - Depending on external state counts too:
Math.random(),Date.now(), reading a global variable. - A function that depends only on its arguments and touches nothing around it is called pure.
- Pure code is easier to test, easier to predict and safer to run in parallel.
- Effects cannot be removed completely: without them there is no UI, no network, no storage. The goal is to isolate and control them.
Quick example
let count = 0;
// impure: the function changes an outer variable
function increment() {
count++;
}
// pure: the result depends only on the arguments
function add(a, b) {
return a + b;
}
increment(); // count is now 1, the outside world changed
add(2, 3); // always 5, nothing around it changedWhat counts as a side effect
A side effect is any change outside the function itself: global variables, console output, a request to a server, DOM mutation, file access and so on. The mirror case counts as well: if a function reads external state, its result is no longer determined by the arguments alone.
| Example | What it does |
|---|---|
console.log('Hello') | Changes the console, that is, the external environment |
alert('Hi!') | Interacts with the user |
document.body.style.color = 'red' | Changes the DOM |
fetch('/api') | Performs an HTTP request |
Math.random() | Depends on external state (the random number generator) |
Date.now() | Depends on the current time |
| Changing a global variable | Changes program state outside the function |
Impure versus pure function
A function with a side effect does not only compute, it also changes program state:
let count = 0;
function increment() {
count++; // changes an outer variable
}A function without side effects works only with its own arguments and touches nothing around it:
function add(a, b) {
return a + b;
}The same contrast shows up with arrays: mutating the input is an effect, returning a new copy is not.
// impure: mutates the caller's array
function addItem(list, item) {
list.push(item);
return list;
}
// pure: returns a new array, the input stays untouched
function addItemPure(list, item) {
return [...list, item];
}Why it matters and how to control it
Code without side effects is easier to test (no mocks of the outside world needed), its result is easier to predict, and it is safer for parallel execution and caching. Yet some effects are unavoidable: without them the program would never talk to a user, a server or a file. So in practice teams do this:
- keep calculations in pure functions and push effects to the edge of the program (event handlers, the request layer talking to
api.example.com, storage writes); - pass external dependencies in as arguments instead of reaching for globals, for example
function greet(now) { ... }rather than callingDate.now()inside; - return new values instead of mutating input objects;
- in tests, substitute that thin effect layer and check the rest of the code directly.
| Trait | Side effect |
|---|---|
| Changes external data | Yes |
| Depends on external state | Yes |
| Returns different results for the same input | Possible |
| Example | console.log, fetch, DOM operations |
| Without side effects | A pure function |
In one sentence: a side effect is any external influence of a function (changing the environment or depending on it) that is not directly tied to its returned result.
Common mistakes
- Treating only writes as effects and missing reads:
Math.random()andDate.now()make a function impure even though they change nothing. - Thinking purity means banning effects. You cannot ban them, you can only move them out of the core logic.
- Mutating a passed object or array and calling it «just an optimisation»: the caller gets changed data and hard bugs follow.
- Hiding a network request or a storage write inside an innocent looking function such as
getUser(), which makes it impossible to call in a test. - Confusing a side effect with returning a value:
returnis not an effect, the effect is everything the function does on top of it.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.