|

Javascript 19 🧬 pure functions

A pure function is a function that adheres to two primary principles: it always produces the same output for the same input, and it has no side effects — meaning it doesn’t modify any external state.


A Quick Look at the Examples

// 1. Simple mathematical operation — pure
function add(a, b) {
    return a + b;
}
console.log(add(2, 3)); // 5

// 2. Array transformation — pure (doesn't modify original)
const numbers = [1, 2, 3, 4];
const doubledNumbers = numbers.map(n => n * 2);
console.log(numbers);       // [1, 2, 3, 4] — unchanged!
console.log(doubledNumbers); // [2, 4, 6, 8]

// 3. Factory function — pure (creates new object)
function createPerson(name, age) {
    return { name, age };
}
const person1 = createPerson("Alice", 30);
console.log(person1); // { name: "Alice", age: 30 }

// 4. Filter — pure (doesn't modify original)
const evenNumbers = numbers.filter(n => n % 2 === 0);
console.log(evenNumbers); // [2, 4]

a. What is a Pure Function?

A pure function is a function that adheres to two primary principles:

1. Determinism

Given the same input, a pure function will always produce the same output.

// ✅ Pure — same input, same output
function add(a, b) {
    return a + b;
}
console.log(add(2, 3)); // 5
console.log(add(2, 3)); // 5 (always)

// ❌ Impure — different output for same input
function randomAdd(a, b) {
    return a + b + Math.random(); // Different every time!
}

2. No Side Effects

A pure function does not modify any external state or variables.

// ✅ Pure — no side effects
function add(a, b) {
    return a + b;
}

// ❌ Impure — modifies external state
let total = 0;
function addToTotal(n) {
    total += n; // Side effect!
    return total;
}

Characteristics of Pure Functions

CharacteristicDescription
ImmutabilityThey do not change the input data — they work on a copy or produce new data
PredictabilitySince they have no side effects, their behavior is entirely predictable based solely on their inputs
TestabilityBecause they’re independent of external state and always return the same result for given inputs, they are easier to test

What Are Side Effects?

A side effect is any observable change to the state outside the function’s scope.

Side EffectExample
Modifying global variablestotal += n;
Mutating input parametersarr.push(item);
Logging to consoleconsole.log(...)
Writing to files/databasesfs.writeFile(...)
Making network requestsfetch(...)
Changing the DOMelement.textContent = ...
Math.random(), Date.now()Non-deterministic

b. Pure Function Examples and Benefits

Example 1: Simple Mathematical Operation

function add(a, b) {
    return a + b;
}
console.log(add(2, 3)); // 5

Why it’s pure:

  • ✅ Same input → same output
  • ✅ No side effects
  • ✅ Doesn’t modify a or b

Example 2: Transforms an Array Without Modifying the Original

const numbers = [1, 2, 3, 4];
const doubledNumbers = numbers.map(n => n * 2);

console.log(numbers);       // [1, 2, 3, 4] — unchanged!
console.log(doubledNumbers); // [2, 4, 6, 8]

Why it’s pure:

  • map() creates a new array — doesn’t modify the original
  • ✅ Same input → same output
  • ✅ Original array is untouched

Compare with the impure version:

// ❌ Impure — mutates the original array
function doubleInPlace(arr) {
    for (let i = 0; i < arr.length; i++) {
        arr[i] *= 2; // Side effect!
    }
    return arr;
}

const numbers = [1, 2, 3, 4];
const doubled = doubleInPlace(numbers);
console.log(numbers); // [2, 4, 6, 8] — MODIFIED!

Example 3: Generates a New Object Without Modifying the Input

function createPerson(name, age) {
    return { name, age };
}

const person1 = createPerson("Alice", 30);
console.log(person1); // { name: "Alice", age: 30 }

Why it’s pure:

  • ✅ Creates a new object each time
  • ✅ Same input → same output
  • ✅ Doesn’t modify external state

Example 4: Filters an Array

const evenNumbers = numbers.filter(n => n % 2 === 0);
console.log(evenNumbers); // [2, 4]

Why it’s pure:

  • filter() creates a new array
  • ✅ Original array is untouched
  • ✅ Same input → same output

Benefits of Using Pure Functions

BenefitDescription
PredictabilityEasier to reason about and understand because they always produce the same output for given inputs
TestabilityCan be tested independently without setting up complex environments or mocking dependencies
ConcurrencySafe to use in concurrent contexts since they don’t depend on external state
ReusabilitySelf-contained, so pure functions can be easily reused across different parts of an application

Complete Example

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pure Functions</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            background: #f8f9fa;
            color: #333;
            line-height: 1.6;
        }
        h1 { color: #007bff; border-bottom: 3px solid #007bff; padding-bottom: 10px; }
        h2 { color: #28a745; border-left: 4px solid #28a745; padding-left: 15px; margin-top: 30px; }
        .demo-box {
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            margin: 15px 0;
        }
        pre {
            background: #1e1e1e;
            color: #d4d4d4;
            padding: 15px;
            border-radius: 8px;
            overflow-x: auto;
            font-family: 'Courier New', monospace;
            font-size: 0.9rem;
            line-height: 1.8;
        }
        .keyword { color: #569cd6; }
        .string { color: #ce9178; }
        .number { color: #b5cea8; }
        .function { color: #dcdcaa; }
        .comment { color: #6a9955; }
        .boolean { color: #569cd6; }
        .error { color: #f48771; }
        .success { color: #4ec9b0; }
        #output {
            background: #e9ecef;
            padding: 15px;
            border-radius: 8px;
            margin-top: 15px;
            min-height: 40px;
            font-family: 'Courier New', monospace;
            font-size: 0.85rem;
            border-left: 4px solid #007bff;
            white-space: pre-wrap;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin: 15px 0;
        }
        th, td {
            padding: 10px;
            border: 1px solid #ddd;
            text-align: left;
        }
        th { background: #007bff; color: white; }
        tr:nth-child(even) { background: #f8f9fa; }
        .btn {
            padding: 10px 20px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 6px;
            font-size: 1em;
            font-weight: bold;
            cursor: pointer;
            margin: 5px;
            transition: all 0.3s;
        }
        .btn:hover {
            background: #0056b3;
            transform: translateY(-2px);
        }
        .btn-success { background: #28a745; }
        .btn-success:hover { background: #1e7e34; }
        .btn-danger { background: #dc3545; }
        .btn-danger:hover { background: #a71d2a; }
        .comparison {
            display: flex;
            gap: 20px;
            flex-wrap: wrap;
            margin: 15px 0;
        }
        .comparison > div {
            flex: 1;
            min-width: 250px;
            padding: 15px;
            border-radius: 8px;
        }
        .pure-box {
            background: #d4edda;
            border-left: 4px solid #28a745;
        }
        .impure-box {
            background: #f8d7da;
            border-left: 4px solid #dc3545;
        }
    </style>
</head>
<body>

    <h1>Pure Functions</h1>

    <div class="demo-box">
        <h2>1. What is a Pure Function?</h2>
        <pre>
<span class="comment">// ✅ Pure — same input, same output, no side effects</span>
<span class="keyword">function</span> <span class="function">add</span>(a, b) {
    <span class="keyword">return</span> a + b;
}

<span class="comment">// ❌ Impure — modifies external state</span>
<span class="keyword">let</span> total = <span class="number">0</span>;
<span class="keyword">function</span> <span class="function">addToTotal</span>(n) {
    total += n; <span class="comment">// Side effect!</span>
    <span class="keyword">return</span> total;
}
        </pre>
    </div>

    <div class="demo-box">
        <h2>2. Pure vs Impure — Side by Side</h2>
        <div class="comparison">
            <div class="pure-box">
                <h3>✅ Pure Function</h3>
                <pre style="background: #fff; color: #333; font-size: 0.85rem;">
<span class="keyword">function</span> <span class="function">double</span>(arr) {
    <span class="keyword">return</span> arr.map(n => n * <span class="number">2</span>);
}

<span class="keyword">const</span> original = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];
<span class="keyword">const</span> doubled = <span class="function">double</span>(original);

<span class="comment">// original: [1, 2, 3] ✅</span>
<span class="comment">// doubled:  [2, 4, 6] ✅</span>
                </pre>
                <p><strong>Original array is unchanged!</strong></p>
            </div>
            <div class="impure-box">
                <h3>❌ Impure Function</h3>
                <pre style="background: #fff; color: #333; font-size: 0.85rem;">
<span class="keyword">function</span> <span class="function">doubleInPlace</span>(arr) {
    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < arr.length; i++) {
        arr[i] *= <span class="number">2</span>; <span class="comment">// Mutates!</span>
    }
    <span class="keyword">return</span> arr;
}

<span class="keyword">const</span> original = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];
<span class="keyword">const</span> doubled = <span class="function">doubleInPlace</span>(original);

<span class="comment">// original: [2, 4, 6] ❌ MODIFIED!</span>
                </pre>
                <p><strong>Original array is destroyed!</strong></p>
            </div>
        </div>
    </div>

    <div class="demo-box">
        <h2>3. Pure Functions in Array Methods</h2>
        <pre>
<span class="keyword">const</span> numbers = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];

<span class="comment">// ✅ map — returns new array</span>
<span class="keyword">const</span> doubled = numbers.<span class="function">map</span>(n => n * <span class="number">2</span>);

<span class="comment">// ✅ filter — returns new array</span>
<span class="keyword">const</span> evens = numbers.<span class="function">filter</span>(n => n % <span class="number">2</span> === <span class="number">0</span>);

<span class="comment">// ✅ reduce — returns single value</span>
<span class="keyword">const</span> sum = numbers.<span class="function">reduce</span>((total, n) => total + n, <span class="number">0</span>);

console.log(numbers);  <span class="comment">// [1, 2, 3, 4] — unchanged!</span>
console.log(doubled);  <span class="comment">// [2, 4, 6, 8]</span>
console.log(evens);    <span class="comment">// [2, 4]</span>
console.log(sum);      <span class="comment">// 10</span>
        </pre>
    </div>

    <div class="demo-box">
        <h2>4. Interactive: Pure Function Playground</h2>
        <div style="margin: 10px 0;">
            <label style="font-weight: bold;">Array:</label>
            <input type="text" id="arrayInput" value="1, 2, 3, 4, 5" style="padding: 8px; width: 200px; border: 2px solid #ddd; border-radius: 6px;">
        </div>
        <button class="btn btn-success" onclick="runPure('double')">Double (pure)</button>
        <button class="btn btn-success" onclick="runPure('filterEven')">Filter Evens (pure)</button>
        <button class="btn btn-success" onclick="runPure('sum')">Sum (pure)</button>
        <button class="btn btn-danger" onclick="runImpure()">Double In Place (impure)</button>
        <button class="btn" onclick="resetArray()">Reset</button>
        <div id="interactiveOutput"></div>
    </div>

    <div class="demo-box">
        <h2>5. Pure Function Benefits</h2>
        <table>
            <tr>
                <th>Benefit</th>
                <th>Description</th>
            </tr>
            <tr>
                <td><strong>Predictability</strong></td>
                <td>Same input always produces same output — easy to reason about</td>
            </tr>
            <tr>
                <td><strong>Testability</strong></td>
                <td>Test independently — no complex setup or mocking needed</td>
            </tr>
            <tr>
                <td><strong>Concurrency</strong></td>
                <td>Safe in concurrent contexts — no shared state</td>
            </tr>
            <tr>
                <td><strong>Reusability</strong></td>
                <td>Self-contained — easy to reuse across the app</td>
            </tr>
            <tr>
                <td><strong>Cacheable</strong></td>
                <td>Results can be memoized (same input = same output)</td>
            </tr>
        </table>
    </div>

    <div class="demo-box">
        <h2>6. Live Output — Pure vs Impure</h2>
        <div id="output">Loading...</div>
    </div>

    <script>
        // ============================================
        // Pure Functions — Live Demo
        // ============================================

        let results = [];

        // ============================================
        // ✅ PURE FUNCTIONS
        // ============================================

        results.push('📌 Pure Functions:\n');

        // Pure: mathematical operation
        function add(a, b) {
            return a + b;
        }
        results.push('  add(2, 3) → ' + add(2, 3));
        results.push('  add(2, 3) → ' + add(2, 3) + ' (always the same!)');
        results.push('');

        // Pure: map (doesn't modify original)
        const originalNumbers = [1, 2, 3, 4];
        const doubled = originalNumbers.map(n => n * 2);

        results.push('  const numbers = [1, 2, 3, 4];');
        results.push('  numbers.map(n => n * 2) → [' + doubled.join(', ') + ']');
        results.push('  numbers (unchanged)    → [' + originalNumbers.join(', ') + ']');
        results.push('');

        // Pure: filter (doesn't modify original)
        const evens = originalNumbers.filter(n => n % 2 === 0);
        results.push('  numbers.filter(n => n % 2 === 0) → [' + evens.join(', ') + ']');
        results.push('  numbers (unchanged)              → [' + originalNumbers.join(', ') + ']');
        results.push('');

        // Pure: reduce
        const sum = originalNumbers.reduce((total, n) => total + n, 0);
        results.push('  numbers.reduce((total, n) => total + n, 0) → ' + sum);
        results.push('  numbers (unchanged)                        → [' + originalNumbers.join(', ') + ']');
        results.push('');

        // Pure: factory function
        function createPerson(name, age) {
            return { name, age };
        }
        const person1 = createPerson("Alice", 30);
        results.push('  createPerson("Alice", 30) → ' + JSON.stringify(person1));
        results.push('');

        // ============================================
        // ❌ IMPURE FUNCTIONS
        // ============================================

        results.push('📌 Impure Functions (for comparison):\n');

        // Impure: modifies external state
        let globalTotal = 0;
        function addToGlobal(n) {
            globalTotal += n; // Side effect!
            return globalTotal;
        }

        results.push('  let globalTotal = 0;');
        results.push('  addToGlobal(5) → ' + addToGlobal(5));
        results.push('  addToGlobal(3) → ' + addToGlobal(3) + ' (depends on previous calls!)');
        results.push('  globalTotal is now → ' + globalTotal);
        results.push('');

        // Impure: mutates input
        function doubleInPlace(arr) {
            for (let i = 0; i < arr.length; i++) {
                arr[i] *= 2;
            }
            return arr;
        }

        const mutableArray = [1, 2, 3];
        results.push('  const arr = [1, 2, 3];');
        results.push('  doubleInPlace(arr) → [' + doubleInPlace([...mutableArray]).join(', ') + ']');
        results.push('  arr (MODIFIED!)    → [' + mutableArray.join(', ') + ']');
        results.push('  ⚠️ Original array was mutated!');
        results.push('');

        // Impure: non-deterministic
        function randomAdd(a, b) {
            return a + b + Math.floor(Math.random() * 10);
        }
        results.push('  randomAdd(2, 3) → ' + randomAdd(2, 3));
        results.push('  randomAdd(2, 3) → ' + randomAdd(2, 3) + ' (different every time!)');
        results.push('');

        // ============================================
        // Comparison Summary
        // ============================================

        results.push('📌 Summary:\n');
        results.push('  ✅ Pure:   Same input → Same output, no side effects');
        results.push('  ❌ Impure: Modifies state, depends on context, non-deterministic');

        document.getElementById('output').textContent = results.join('\n');

        // ============================================
        // Interactive Functions
        // ============================================

        // ✅ Pure functions
        const pureFunctions = {
            double: (arr) => arr.map(n => n * 2),
            filterEven: (arr) => arr.filter(n => n % 2 === 0),
            sum: (arr) => arr.reduce((total, n) => total + n, 0)
        };

        // Keep track of the current array
        let currentArray = [1, 2, 3, 4, 5];

        function getArray() {
            const input = document.getElementById('arrayInput').value;
            return input.split(',').map(n => Number(n.trim())).filter(n => !isNaN(n));
        }

        function runPure(operation) {
            const arr = getArray();
            const output = document.getElementById('interactiveOutput');
            const original = [...arr]; // Snapshot

            const result = pureFunctions[operation](arr);

            let resultDisplay = Array.isArray(result) ? '[' + result.join(', ') + ']' : result;

            output.innerHTML = `
                <p><strong>✅ Pure Function: ${operation}</strong></p>
                <p>Input:  <code>[${original.join(', ')}]</code></p>
                <p>Output: <code style="color: #28a745;">${resultDisplay}</code></p>
                <p style="color: #28a745;">Original array is unchanged: <code>[${arr.join(', ')}]</code></p>
            `;
        }

        function runImpure() {
            const arr = getArray();
            const output = document.getElementById('interactiveOutput');
            const original = [...arr]; // Snapshot before

            // Impure — mutates the array
            for (let i = 0; i < arr.length; i++) {
                arr[i] *= 2;
            }

            output.innerHTML = `
                <p><strong>❌ Impure Function: doubleInPlace</strong></p>
                <p>Before: <code>[${original.join(', ')}]</code></p>
                <p>After:  <code style="color: #dc3545;">[${arr.join(', ')}]</code></p>
                <p style="color: #dc3545;">⚠️ The original array was MODIFIED!</p>
            `;

            // Update the input to reflect the mutation
            document.getElementById('arrayInput').value = arr.join(', ');
        }

        function resetArray() {
            document.getElementById('arrayInput').value = '1, 2, 3, 4, 5';
            document.getElementById('interactiveOutput').innerHTML = '';
        }
    </script>

</body>
</html>

Quick Reference

Pure Function Checklist

QuestionPure?
Same input → same output?✅ Must be YES
Modifies external state?❌ Must be NO
Modifies input parameters?❌ Must be NO
Depends on external state?❌ Must be NO
Uses Math.random() or Date.now()?❌ Must be NO
Logs to console?⚠️ Technically a side effect

Pure vs Impure

AspectPureImpure
Same input → same output✅ Yes❌ Not guaranteed
Side effects✅ None❌ May have
Mutates inputs✅ No❌ May mutate
Testability✅ Easy❌ Hard
Predictability✅ High❌ Low
Cacheable✅ Yes❌ No

Common Side Effects

Side EffectExample
Modifying globalstotal += n;
Mutating inputsarr.push(x);
Console outputconsole.log(...)
DOM changesel.textContent = ...
Network requestsfetch(...)
File I/Ofs.writeFile(...)
Random valuesMath.random()
Current timeDate.now()

Best Practices

Do This:

// Pure: returns new array
function double(arr) {
    return arr.map(n => n * 2);
}

// Pure: returns new object
function updateUser(user, newName) {
    return { ...user, name: newName };
}

// Pure: doesn't modify inputs
function addItem(arr, item) {
    return [...arr, item];
}

// Pure: deterministic
function calculateTotal(items) {
    return items.reduce((sum, item) => sum + item.price, 0);
}

// Separate pure logic from side effects
function calculateTax(amount) {       // Pure
    return amount * 0.08;
}
function displayTotal(amount) {       // Impure (DOM side effect)
    document.getElementById('total').textContent = calculateTax(amount);
}

Don’t Do This:

// Impure: mutates input
function addItem(arr, item) {
    arr.push(item); // ❌ Side effect!
    return arr;
}

// Impure: modifies global state
let count = 0;
function increment() {
    count++; // ❌ Side effect!
}

// Impure: non-deterministic
function getId() {
    return Math.random(); // ❌ Different every time!
}

// Impure: modifies object directly
function updateUser(user, name) {
    user.name = name; // ❌ Mutates input!
    return user;
}

// Impure: depends on external state
let taxRate = 0.08;
function calculateTax(amount) {
    return amount * taxRate; // ❌ Depends on external variable!
}

Common Pitfalls

PitfallProblemSolution
Mutating arraysOriginal data corruptedUse map, filter, spread
Mutating objectsShared references affectedUse spread { ...obj }
Using push/popModifies originalUse concat or spread
Global stateHard to test, unpredictablePass as parameter
Math.random()Non-deterministicPass random value as parameter

Pure vs Impure — Visual

┌─────────────────────────────────────┐
│  PURE FUNCTION                      │
│                                     │
│  Input ────→ [Function] ────→ Output│
│                                     │
│  • No side effects                  │
│  • Same input = same output         │
│  • Doesn't touch anything outside   │
└─────────────────────────────────────┘

┌─────────────────────────────────────┐
│  IMPURE FUNCTION                    │
│                                     │
│              ┌──────────────┐       │
│  Input ────→ │  [Function]  │ ────→ Output
│              └──────┬───────┘       │
│                     │               │
│                     ▼               │
│              ┌──────────────┐       │
│              │ Global State │       │
│              │ DOM / Files  │       │
│              │ Network / DB │       │
│              └──────────────┘       │
│                                     │
│  • Side effects                     │
│  • Same input ≠ same output         │
└─────────────────────────────────────┘

Functional Programming Connection

Pure functions are the foundation of functional programming:

ConceptDescription
Pure FunctionsBuilding blocks — no side effects
ImmutabilityNever modify data — create new copies
Higher-Order FunctionsFunctions that take/return functions
CompositionCombine pure functions into pipelines
MemoizationCache results (only works with pure functions)
// Functional pipeline with pure functions
const result = [1, 2, 3, 4, 5]
    .filter(n => n % 2 === 0)   // Pure
    .map(n => n * 10)           // Pure
    .reduce((sum, n) => sum + n, 0); // Pure
console.log(result); // 60

Pro Tip: Pure functions are the building blocks of reliable software. They’re predictable (same input → same output), testable (no setup needed), cacheable (memoization works), and safe in concurrent environments. Aim to make as much of your code pure as possible, and isolate impure operations (DOM, network, files) to the edges of your application. Remember: map, filter, and reduce are pure — they return new arrays without modifying the original. But push, pop, sort, and splice mutate the array — avoid them in favor of pure alternatives!


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!