Suggest an editImprove this articleRefine the answer for “Wrapper function”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**A wrapper function is a function that wraps another function or a piece of code in order to add extra behaviour, control or a simpler call signature.** It breaks nothing in the original: it calls it inside itself and adds logging, validation, permission checks, error handling, caching or timing on top. Technically it is a higher-order function: it takes a function and returns a new one with the same signature. ```javascript function withLogging(fn) { return function (...args) { console.log(`call ${fn.name}`, args); return fn(...args); }; } ``` **Key point:** a wrapper changes the behaviour around a function without changing the function itself, so one behaviour template is reused across many functions.Shown above the full answer for quick recall.Answer (EN)Image**A wrapper function is a function that wraps another function or a piece of code in order to add extra behaviour, control, or a simpler call.** Put simply, it is a layer around a function that breaks nothing but adds something: logging, validation, error handling, caching and so on. ## Theory ### TL;DR - A wrapper takes a function and returns a new function that calls the original inside itself. - It is a higher-order function, the classic way to add cross-cutting behaviour. - The original function is not modified, so it can still be used without the wrapper. - Typical jobs: logging, metrics, `try/catch`, permission checks, caching, throttling. - The same pattern underlies decorators and middleware. ### Quick example ```javascript function greet(name) { return `Hello, ${name}!`; } function withLogging(fn) { return function (...args) { console.log(`Calling ${fn.name} with arguments:`, args); const result = fn(...args); console.log('Result:', result); return result; }; } const loggedGreet = withLogging(greet); loggedGreet('Maria'); ``` Output: ```text Calling greet with arguments: [ 'Maria' ] Result: Hello, Maria! ``` Here `withLogging` is the wrapper function that adds extra behaviour on top of the plain `greet` function. ### The core idea You take an existing function or operation and create a new one that calls it inside itself, but with something extra around the call. For example: - add logging before the call; - measure execution time; - check the arguments; - handle errors with `try/catch`. To stay transparent, the wrapper should accept `...args`, return the original's result and, when a correct `this` matters, call the function through `fn.apply(this, args)`. ### Error handling ```javascript function riskyOperation() { throw new Error('Something went wrong!'); } function safeWrapper(fn) { return function (...args) { try { return fn(...args); } catch (err) { console.error('Error while calling the function:', err.message); return null; } }; } const safeOp = safeWrapper(riskyOperation); safeOp(); // Error while calling the function: Something went wrong! ``` Now even if the inner function throws, the surrounding code keeps working. ### Measuring execution time ```javascript 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.34ms ``` ### An asynchronous wrapper For an `async` function the wrapper has to be asynchronous too, otherwise `try/catch` will not catch a rejected promise. ```javascript 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 failed:', e); return null; } }; } const safeFetch = withErrorHandling(fetchData); safeFetch(); ``` ### A wrapper as a decorator: permission checks ```javascript 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 denied ``` ### Why 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 | Build one behaviour template for many functions | | Functional programming | Use higher-order functions | ### Summary table | Property | Description | | --- | --- | | What it is | A function that calls another one inside itself | | Goal | Add or change behaviour without touching the original | | Type | Higher-order function | | Typical examples | Logging, caching, validation, `try/catch`, metrics | | Benefits | Reusable, safe, readable | ### Common mistakes - Not returning the original function's result: the wrapper swallows the value and the call suddenly yields `undefined`. - Wrapping an `async` function with a synchronous wrapper: the error becomes an unhandled promise rejection and `try/catch` stays silent. - Losing `this`: when wrapping an object's method, call `fn.apply(this, args)` instead of `fn(...args)`. - Forgetting that the new function has a different `fn.name` and `fn.length`, so code that reads the name or the arity breaks. - Stacking wrappers without restraint: five layers around one function make the stack trace unreadable and hide where the error really came from.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.