Lodash _.once() method
What you’ll learn
- How
_.onceruns the inner function exactly one time. - How the cached return value behaves when callers pass different arguments afterward.
- How once compares to
_.before, manual flags, and_.memoize. - Pitfalls around side effects,
this, and expecting per-call recomputation.
Prerequisites
Helpful reads: _.negate(), _.before(), and the Function hub.
- Higher-order functions: functions that return or consume other functions.
- Closures: inner functions that retain variables from an enclosing scope.
Overview
_.once(func) builds a wrapper that calls func at most once. The first return value is stored and reused, even when future calls supply different arguments.
Syntax
_.once(func)- func: function to invoke only on the first wrapper call.
- returns: wrapped function that replays the first computed result.
One-time expensive computation
Share a single initializer across modules without manual booleans.
import once from "lodash/once";
const loadConfig = once(() => {
console.log("fetching config...");
return { apiUrl: "https://example.test" };
});
loadConfig(); // logs once
loadConfig(); // silent — returns cached objectStable identity across calls
When func constructs an object, every caller receives the same reference afterward.
import once from "lodash/once";
const getSingleton = once(() => ({ createdAt: Date.now() }));
const a = getSingleton();
const b = getSingleton();
Object.is(a, b); // trueArguments after the first call
Later arguments no longer reach func—they exist only on the first invocation.
import once from "lodash/once";
const summarize = once((label, value) => ({
label,
value
}));
summarize("first", 1); // { label: "first", value: 1 }
summarize("ignored", 99); // still first object — inner func never reruns📋 _.once vs _.before vs manual flags
| Approach | Best for | Trade-off |
|---|---|---|
_.once | Exactly one execution shared by every caller | Always ignores recomputation for fresh inputs |
_.before(n, func) | Allow multiple runs until a cutoff | Requires tuning n and mental model of counters |
| Manual flag | Full inline control | Easy to forget resets or thread-safety in async flows |
Pitfalls to avoid
Expecting per-call recomputation
Once never recomputes; reach for memoize or plain functions when inputs should produce distinct outputs.
thisLost component context
If func relies on dynamic this, bind explicitly—otherwise first-call context is baked into behavior unpredictably.
Hidden one-shot side effects
Observers expect idempotent wrappers; document when listeners mutate external state only during the first hit.
❓ FAQ
Summary
- Purpose:
_.onceguarantees a single evaluation while exposing a reusable wrapper. - Mental model: think frozen first result, not keyed caching.
- Next: Lodash _.overArgs(), revisit Lodash _.negate(), or read official _.once docs.
Lodash _.once(func) stores the value returned from the first successful invocation and replays it for every later call—so expensive setup runs exactly once while callers keep passing updated arguments into the wrapper.
6 people found this page helpful
