wrapper function
A wrapper function is a function that wraps another function or piece of code to add extra behavior, control, or simplify the call.
In simpler terms:
A wrapper function is a "layer" around another function that breaks nothing, but adds something: logging, validation, error handling, caching, and so on.
Main idea
You take an existing function (or operation) and create a new one that calls it inside itself, but with something "on top".
For example:
- add logging before the call;
- measure the execution time;
- add argument validation;
- or, for example, handle errors via try/catch.
Example 1 - a simple wrapper with logging
function greet(name) {
return `Hello, ${name}!`;
}
function withLogging(fn) {
return function(...args) {
console.log(`Calling function ${fn.name} with arguments:`, args);
const result = fn(...args);
console.log(`Result:`, result);
return result;
};
}
const loggedGreet = withLogging(greet);
loggedGreet('Tim');Output:
Calling function greet with arguments: [ 'Tim' ]
Result: Hello, Tim!Here withLogging is a wrapper function that adds extra behavior "on top" of the regular greet function.
Example 2 - a wrapper for error handling
function riskyOperation() {
throw new Error('Something went wrong!');
}
function safeWrapper(fn) {
return function(...args) {
try {
return fn(...args);
} catch (err) {
console.error('Error calling the function:', err.message);
return null;
}
};
}
const safeOp = safeWrapper(riskyOperation);
safeOp(); // Error calling the function: Something went wrong!Now even if the inner function throws, the code does not break.
Example 3 - measuring execution time
function heavyTask() {
for (let i = 0; i < 1e7; i++) {}
}
function measureTime(fn) {
return function(...args) {
const start = performance.now();
fn(...args);
const end = performance.now();
console.log(`Execution time: ${(end - start).toFixed(2)}ms`);
};
}
const measuredTask = measureTime(heavyTask);
measuredTask(); // Execution time: 12.34msExample 4 - a wrapper function in async code
async function fetchData() {
const res = await fetch('https://api.example.com/data');
return res.json();
}
function withErrorHandling(fn) {
return async function(...args) {
try {
return await fn(...args);
} catch (e) {
console.error('Request error:', e);
return null;
}
};
}
const safeFetch = withErrorHandling(fetchData);
safeFetch();This is already an async wrapper that automatically catches errors.
Example 5 - a wrapper for "decorators" (a similar pattern)
function authWrapper(fn) {
return function(user, ...args) {
if (!user.isAdmin) {
throw new Error('Access denied');
}
return fn(user, ...args);
};
}
function deletePost(user, postId) {
console.log(`Post ${postId} deleted`);
}
const deletePostWithAuth = authWrapper(deletePost);
deletePostWithAuth({ isAdmin: true }, 42); // Post 42 deleted
deletePostWithAuth({ isAdmin: false }, 42); // Error: Access deniedWhy wrapper functions are useful
| Goal | Example |
|---|---|
| Extending functionality | Add logging, metrics, caching |
| Security | Check access rights or a token |
| Error handling | Wrap risky operations in try/catch |
| Reuse | Create a "behavior" template for many functions |
| Functional programming | Use higher-order functions |
Summary
| Property | Description |
|---|---|
| What it is | A function that calls another one inside itself |
| Goal | Add or change behavior without changing the original |
| Type | Higher-order function |
| Typical examples | Logging, cache, validation, try/catch, metrics |
| Pros | Reusable, safe, readable |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.