Allow One Function Call
EasyUpdated: Aug 2, 2025
Practice on:
Problem
Given a function fn, return a new function that is identical to the original function except that it ensures fn is called at most once.
- The first time the returned function is called, it should return the same result as
fn. - Every subsequent time it is called, it should return
undefined.
Examples
Example 1
Input: fn = (a,b,c) => (a + b + c), calls = [[1,2,3],[2,3,6]]
Output: [{"calls":1,"value":6}]
Explanation:
const onceFn = once(fn);
onceFn(1, 2, 3); // 6
onceFn(2, 3, 6); // undefined, fn was not called
Example 2
Input: fn = (a,b,c) => (a * b * c), calls = [[5,7,4],[2,3,6],[4,6,8]]
Output: [{"calls":1,"value":140}]
Explanation:
const onceFn = once(fn);
onceFn(5, 7, 4); // 140
onceFn(2, 3, 6); // undefined, fn was not called
onceFn(4, 6, 8); // undefined, fn was not called
Constraints
callsis a valid JSON array1 <= calls.length <= 101 <= calls[i].length <= 1002 <= JSON.stringify(calls).length <= 1000
Solution
Method 1 – Using Closure to Track Calls
Intuition
The key idea is to use a closure to remember whether the function has already been called. By storing a flag inside the returned function, we can ensure the original function is only executed once, and subsequent calls return undefined.
Approach
- Define a function
onceWithClosurethat takes a functionfnas input. - Inside
onceWithClosure, declare a boolean variable (e.g.,called) initialized tofalse. - Also declare a variable to store the result of the first call.
- Return a new function that:
- Checks if
calledisfalse. - If so, set
calledtotrue, callfnwith the provided arguments, store and return the result. - If
calledistrue, returnundefined.
- This ensures
fnis only called once, regardless of how many times the returned function is invoked.
Code
Javascript
function onceWithClosure(fn) {
let called = false;
let result;
return function(...args) {
if (!called) {
called = true;
result = fn(...args);
return result;
}
return undefined;
};
}
Typescript
function onceWithClosure<T extends (...args: any[]) => any>(fn: T): (...args: Parameters<T>) => ReturnType<T> | undefined {
let called = false;
let result: ReturnType<T>;
return (...args: Parameters<T>): ReturnType<T> | undefined => {
if (!called) {
called = true;
result = fn(...args);
return result;
}
return undefined;
};
}
Complexity
- ⏰ Time complexity:
O(1)per call, as it only checks a flag and possibly callsfnonce. - 🧺 Space complexity:
O(1), only a couple of variables are stored in the closure.