How Lodash _.once Guarantees Single Execution
The Lodash _.once method guarantees that a specified
function is invoked only once by wrapping it within a closure that
tracks execution state and caches the output. This article explains the
internal mechanics behind this behavior, detailing how
_.once utilizes higher-order functions, manages internal
invocation counters, and recycles references to prevent redundant
executions and optimize memory usage.
The Underlying Delegation
to _.before
In the Lodash source code, _.once(func) does not
implement standalone logic from scratch. Instead, it is a direct alias
for _.before(2, func). The _.before method
creates a wrapper function that allows the target function to be invoked
up to \(n - 1\) times. By passing
2 as the threshold argument, Lodash restricts execution
strictly to a single time (\(2 - 1 =
1\)).
State Management via Closures
When _.once is called, it creates a closure containing
three critical private variables:
func: A reference to the original function passed into_.once.n: A counter initialized to the threshold (in this case,2).result: A variable reserved to store the return value of the initial execution.
Because these variables live in the lexical environment of the wrapper, they persist across multiple calls to the generated function without leaking into the global scope.
The Execution and Mutation Phase
When the wrapped function is called for the first time:
- Threshold Check and Decrement: Lodash checks if
nis greater than0. Becausenbegins at2, the check succeeds, andnis decremented to1. - Invocation: Because
n <= 1now evaluates to true, the wrapper invokes the originalfuncusingfunc.apply(this, arguments), capturing the providedthisbinding and arguments. - Result Caching: The returned value from the
invocation is assigned to the closure's
resultvariable. - Reference Cleanup: To allow garbage collection and
prevent subsequent executions, the internal
funcvariable is explicitly set toundefinedoncen <= 1.
Handling Subsequent Invocations
On the second and any subsequent calls:
- The wrapper again checks the counter condition. Since
nwas decremented to1during the first run, the invocation condition fails. - The original function is never called again. If an attempt were
somehow made,
funcis nowundefined. - The wrapper immediately skips execution and returns the stored
result.
Simplified Implementation Example
The core logic of Lodash's approach can be represented in pure JavaScript as follows:
function once(func) {
let result;
let called = false;
return function(...args) {
if (!called) {
called = true;
result = func.apply(this, args);
func = null; // Free reference for garbage collection
}
return result;
};
}Through this combination of closures, explicit invocation bounds, and reference clearing, Lodash ensures deterministic single execution while consistently returning the initial result on all subsequent calls.