Mastering once(fn) in JavaScript


📌 Problem Statement
Implement a function once(fn)
which accepts another function fn
and returns a new function. This new function ensures that:
fn
is executed only once, no matter how many times the new function is called.On the first call,
fn
should run and return its result.On subsequent calls, the function should return the result from the first call, without re-invoking
fn
.
✅ Input:
A function
fn
(can be sync or async)The returned function can accept any number of arguments
✅ Output:
- A function that runs
fn
once and returns the same result for all future calls.
🧠 Final Code Solution
function once(fn) {
let called = false;
let ans;
return function (...args) {
if (!called) {
ans = fn.apply(this, args);
called = true;
}
return ans;
};
}
🔍Questions & Concepts
1. ❓ Why not call the function directly using fn(...args)
?
Calling fn(...args)
works only for pure functions. But if fn
depends on this
(like a method in an object), you’ll break the context. Using:
fn.apply(this, args);
Ensures correct
this
bindingWorks with array-based arguments from
...args
It’s safer and more flexible in real-world scenarios.
2. ❓ What is the difference between call
and apply
?
Method | Arguments Format | Example |
call | Individual arguments | fn.call(this, arg1, arg2) |
apply | Arguments as an array | fn.apply(this, [arg1, arg2]) |
Since we’re using ...args
which collects arguments into an array, apply()
is the more natural choice.
3. ❓ What is a Higher-Order Function?
A higher-order function is one that:
Accepts another function as input
OR returns a function
In our case, once(fn)
returns a function and wraps extra logic around fn
, making it a classic higher-order utility.
4. ❓ What is a Closure?
Closures allow a function to remember and access its lexical scope even after the outer function has finished executing.
Here:
let called = false;
let ans;
These are preserved between invocations of the returned function. That’s how we remember if fn
has been called and what it returned.
5. ❓ Real-Life Use Case: When is this Useful?
I used this pattern in a React app where I initialized an analytics SDK. To prevent duplicate initialization (even on re-renders), I wrapped the
init()
function insideonce()
. This ensured it ran only the first time.
Other Examples:
Preventing double form submissions
One-time event bindings (like
addEventListener
)Lazy-loading external scripts
Showing modals/tooltips once
🧠 Wrap-Up
The once()
function may look small, but it touches on major JavaScript concepts like closures, higher-order functions, and execution context.
Question Credit : https://namastedev.com/practice
Subscribe to my newsletter
Read articles from Gaurav Kumar Maurya directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
