HOF.visualizer

Higher-Order Functions

Unlock the power of JavaScript functional programming. Master concepts of functions that receive, build, and operate on other functions through live interactive visual tools.

11 interactive demoslive visualizationreal code

1. Array Methods (map, filter, reduce)

The fundamental trio of JavaScript functional programming. They accept callbacks to transform, select, or compile array data.

🛒 Interactive Cart Calculator

Cart is empty. Add items above to trigger higher-order operations!

array-processing-pipeline.ts
// Real-world: E-commerce cart processing
const cart = [
{ name: 'Laptop', price: 999, category: 'Electronics' },
{ name: 'Book', price: 15, category: 'Education' },
{ name: 'Headphones', price: 199, category: 'Electronics' }
];
// map: Transform data (get prices with tax)
const pricesWithTax = cart.map(item => ({
...item,
priceWithTax: item.price * 1.1
}));
// filter: Select specific items
const electronics = cart.filter(item => item.category === 'Electronics');
// reduce: Aggregate values
const total = cart.reduce((sum, item) => sum + item.price, 0);

2. Function Composition & Pipelines

Compose intricate operations from simple, atomic functions. The output of one function feeds seamlessly into the input of the next.

📝 Username Sanitizer

functional-pipeline.ts
// Real-world: Data validation pipeline
const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
const trim = (str) => str.trim();
const toLower = (str) => str.toLowerCase();
const removeSpecialChars = (str) => str.replace(/[^a-z0-9]/g, '');
const addPrefix = (prefix) => (str) => `${prefix}_${str}`;
const sanitizeUsername = pipe(
trim,
toLower,
removeSpecialChars,
addPrefix('user')
);
// Usage: " John_Doe@123 " → "user_johndoe123"

3. Function Factories & Closures

Spin up customized, high-order utility functions dynamically. Leverage scopes to protect private variables and encapsulate states.

🔧 Discount Calculator Factory

%
Click "Create Calculator" above to lock a discount rate into a closure lexical environment.
closure-factory.ts
// Real-world: API client factory with auth
const createAPIClient = (baseURL, apiKey) => {
// Private state via closure
let requestCount = 0;
return {
get: async (endpoint) => {
requestCount++;
console.log(`Request #${requestCount} to ${baseURL}${endpoint}`);
return fetch(`${baseURL}${endpoint}`, {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
},
getRequestCount: () => requestCount
};
};
// Usage
const githubAPI = createAPIClient('https://api.github.com', 'ghp_xxx');

4. Debounce & Throttle (Performance)

Optimize expensive functions by controlling execution speed. Ideal for preventing server strain during fast user typing or scrolls.

⏱️ Type to Search (Live Test)

Normal Execution

Triggers on every keydown

0
Waiting for input...
Debounced (400ms)

Triggers 400ms after typing stops

0
Waiting for input...
Waiting for events... Type above to populate the timeline
debounce-performance.ts
// Real-world: Search input optimization
const debounce = (fn, delay) => {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), delay);
};
};
// Usage: Wait 300ms after user stops typing
const searchInput = document.getElementById('search');
const handleSearch = debounce((query) => {
console.log('Searching for:', query);
// Perform API call
}, 300);
searchInput.addEventListener('input', (e) => handleSearch(e.target.value));

5. Middleware Pattern (Express & Next.js Style)

Chain series of processing blocks sequentially. Verify, modify headers, validate inputs, and handle errors. Control flows and short-circuits.

🛡️ Request Middleware Chain

middleware-pipeline.ts
// Real-world: HTTP request pipeline
const createMiddlewarePipeline = (...middlewares) => {
return (ctx) => {
let index = 0;
const next = () => {
if (index >= middlewares.length) return;
const middleware = middlewares[index++];
middleware(ctx, next);
};
next();
return ctx;
};
};
// Middleware functions
const logger = (ctx, next) => {
ctx.logs.push(`Request: ${ctx.url}`);
next();
};
const auth = (ctx, next) => {
if (!ctx.token) throw new Error('Unauthorized');
ctx.user = { id: 1, name: 'John' };
next();
};

6. Memoization (Caching Higher-Order Wrapper)

Optimize recursive or CPU-bound tasks by saving intermediate computations. Intercept subsequent executions to pull instantly from a closure cache database.

🧠 Expensive Fibonacci Engine

Memoize Wrapper (HOF Caching)Wraps function in internal closure storage
Closure Memory Database
Closure storage database is empty. Calculate N index values above with Memoization enabled.
memoization-caching.ts
// Real-world: Cache expensive computations
const memoize = (fn) => {
const cache = {};
return (...args) => {
const key = JSON.stringify(args);
if (key in cache) {
return cache[key]; // Cache hit!
}
const result = fn(...args);
cache[key] = result; // Cache store
return result;
};
};
// Recursive Fibonacci (Exponential cost: O(2^n))
const fib = (n) => {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
};
const memoizedFib = memoize(fib);
// fib(35) -> Takes ~100ms & 29M operations
// memoizedFib(35) -> First run takes ~2ms, second takes 0ms!

7. Function Currying & Partial Application

Deconstruct a multi-argument function into a chain of single-argument nesting functions. Lock arguments step-by-step to compile custom, highly reusable derivatives.

🔗 Curried Step-by-Step Logger

log(level) Closure (level = "?")
(component) Closure (component = "?")
(message) => Wait for final resolve...
currying-closures.ts
// Real-world: Multi-stage curried logger
const log = (level) => (component) => (message) => {
const timestamp = new Date().toLocaleTimeString();
return `[${timestamp}] [${level}] [${component}] ${message}`;
};
// Partial Application stages
const errorLog = log('ERROR'); // locks level
const dbErrorLog = errorLog('Database'); // locks component
// Usage
dbErrorLog('Connection timeout');
// Output: "[17:25:00] [ERROR] [Database] Connection timeout"

8. Once Wrapper HOF (Preventing Duplicates)

Restrict a function to a single invocation. Perfect for securing forms, checkout submissions, and critical one-shot initialization events.

🛡️ Checkout Payment Form

Unsecured Button

Can execute multiple times. Risky checkout double-billing!

Waiting for click...
Once-wrapped HOF

Locked inside `once()` closure. Absolute duplicate protection!

Waiting for click...
State variable: hasRun
false (Available)
once-executor.ts
// Real-world: Prevent duplicate submissions
const once = (fn) => {
let hasRun = false;
let result;
return (...args) => {
if (hasRun) {
return result; // Locked
}
hasRun = true;
result = fn(...args);
return result;
};
};
// Checkout call wrapped with HOF
const processCheckout = once((orderId) => {
console.log('Charging payment for:', orderId);
return 'Payment Succeeded';
});

Throttle

Rate-limit a function to fire at most once per interval

HOF
1500ms
Limit
0
Fired
0
Blocked

Click rapidly — throttle allows execution at most every 1500ms.

▶ Ready to fire
Event Log

Start clicking to see events…

throttle.ts
function throttle(fn, limit) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
// Only fire if enough time has elapsed
if (now - lastCall >= limit) {
lastCall = now;
fn.apply(this, args); // execute the wrapped fn
}
// Otherwise: silently drop this invocation
};
}
// Usage
const throttledSave = throttle(saveDocument, 1500);
// No matter how fast the user types…
editor.on('change', throttledSave);
// …saveDocument runs at most once every 1500ms

Retry with Backoff

Wrap async functions with automatic exponential-backoff retry logic

HOF

Configuration

Attempt Timeline

Run to see retry attempts…

withRetry.ts
async function withRetry(fn, maxRetries, baseDelay) {
for (let attempt = 1; attempt <= maxRetries + 1; attempt++) {
// Exponential backoff: 0ms, 600ms, 1200ms, 2400ms
const delay = attempt === 1 ? 0 : baseDelay * 2 ** (attempt - 2);
if (delay > 0) await sleep(delay);
try {
return await fn(); // execute wrapped function
} catch (err) {
if (attempt > maxRetries) throw err; // exhausted
console.warn('Attempt ' + attempt + ' failed — retrying...');
}
}
throw new Error('Unreachable');
}
// Usage
const robustFetch = () =>
withRetry(() => fetch('/api/data').then(r => r.json()), 3, 600);

Performance Decorator

Wrap any function to automatically audit execution time & call count

HOF
0
Total Runs
Avg (ms)
Slowest (ms)

Decorate & Run a Function

Audit Log

Run a function above to see audit records…

withPerformance.ts
function withPerformance(fn, label) {
let callCount = 0; // closed-over state
return function(...args) {
callCount++;
const start = performance.now();
const result = fn.apply(this, args); // call original fn
const duration = performance.now() - start;
console.log(
'[' + label + '] call #' + callCount +
' took ' + duration.toFixed(2) + 'ms'
);
return result; // transparent passthrough
};
}
// Usage - zero changes to original functions!
const auditedFetch = withPerformance(fetch, 'fetch');
const auditedRender = withPerformance(render, 'render');
const auditedSort = withPerformance(sort, 'sort');

Why Higher-Order Functions Matter

HOFs elevate your code to be highly declarative, composable, and reusable. Instead of cluttering your logic with endless loops and branches, you define what needs to be done, leaving the implementation details abstracted away.

Abstract repetitive logic blocks (loops, validations)
Create highly configurable, reusable utility layers
Enable advanced function pipelines & compositions
Provide secure state protection with closures
Greatly increase unit testing isolation & coverage
Promote stateless, declarative software design
React Hook

Custom Hooks

useFetch, useLocalStorage, and useDebounce are higher-order callbacks that encapsulate component states, hooks, and side-effects.

Node.js

Express Middleware

app.use() registers variadic handlers that process HTTP requests, inspect body payloads, authenticate headers, and catch pipeline errors.

Testing

Mock Functions

jest.fn() and sinon.spy() are wrapper higher-order functions that hook targets to monitor execution counts, arguments, and throw states.

Redux

Store Enhancers

applyMiddleware() intercepts standard dispatch pipelines, injecting loggers, thunks, or actions to enhance state management.