Is It Really a Function? The Full Checklist
Every rule this series builds up for what actually counts as a function, in one table, so you don't have to hold all nine posts in your head at once.
Nine posts built this definition one rule at a time. This page collects all of it in one place, so you can check a piece of code against it without re-reading the series.
The Checklist
| # | Rule | What Breaks It |
|---|---|---|
| 1 | Must hand back a value through return | No return keyword at all → it's a procedure, not a function |
| 2 | Can only call other functions, never a procedure | Calling a procedure and returning its result → taints the caller too |
| 3 | The output must have a real relationship to the input | return 40 no matter what comes in → no relationship, no function |
| 4 | Every input must arrive only through parameters | Reading a variable sitting outside the function → an indirect input (a side cause) |
| 5 | Every output must leave only through return | Mutating anything outside itself (a shared object, the DOM, a database) → a side effect |
| 6 | The same input must always produce the same output | A getter using Math.random() or the current time → different output, same input |
| 7 | Purity is judged at the call, not just the definition | A cleanly-written function called with a shared, mutable object → the call can still be untrustworthy |
| 8 | An outside value is fine to read, as long as it's never reassigned anywhere in the program | A const (or var) that does get reassigned somewhere else → breaks the guarantee, keyword or not |
The One-Line Version of All Eight Rules
If you only remember one test, make it this one: could you replace this function call with its return value, and nothing else in the program would change? That's referential transparency, and every rule above is really just a piece of what it takes to earn it.
Two Things That Look Like Exceptions, But Aren't
No input is still a valid input. A function like currentHour() takes nothing, but it still describes a relationship: calling it, at a given moment, always tells you the same thing about that moment.
undefined is still a valid output. Looking up a key that was never set should honestly return undefined. That's not a failure of rule 3, it's the correct answer to the question being asked. Full explanation.
One Mindset Shift, Not a Rule
In real code, you often can't verify every rule above with total certainty, you can't always see every line that might touch a value. Purity ends up being a confidence level, not a strict pass or fail. The goal is sorting your code into "I'd stake real confidence on this" and "I wouldn't," then shrinking the second pile. Full explanation.
What to Do When Code Fails the Checklist
Failing a rule doesn't mean deleting the code. It means choosing one of these, roughly in order of preference:
- Write it pure from the start, if the design allows it.
- Refactor an existing impure function to be pure.
- Extract the impurity, splitting computation from the side effect.
- Wrap it, if you own the function doing the mutating.
- Adapt around it, saving and restoring state, if you don't.
- If none of those work, at least make it obvious. Name it honestly, keep it in one predictable place, so the next person debugging it knows exactly where to look.
Keep reading