You've wired up an init() that sets up listeners, opened a "Save" handler that creates a database row, or shipped an analytics call you'd be embarrassed to fire twice. once is the standard guard: it wraps a function so it runs the first time you call it and then turns into a no-op that returns the original result forever after.
Implement once(fn). It accepts any function fn and returns a new function. The first time the returned function is called, it invokes fn with the arguments you passed and remembers the return value. Every subsequent call ignores its arguments and returns the remembered value — without calling fn again.
function once(fn) {
// returns a new function. The first call invokes fn(...args) and
// caches the result. Every later call returns the cached result
// without calling fn again.
}
let calls = 0;
const init = once(() => {
calls++;
return 'ready';
});
init(); // 'ready' (calls === 1)
init(); // 'ready' (calls === 1, fn was not called again)
init(); // 'ready' (calls === 1)
const add = once((a, b) => a + b);
add(2, 3); // 5 — fn runs with (2, 3)
add(10, 7); // 5 — args ignored, cached result returned
fn; later calls ignore whatever you pass them.this binding — when the returned function is called as a method (obj.cb()), fn should see obj as this on the first call.fn returns, including undefined, null, or 0 — all are valid cached results.fn, even with different arguments.once(fn) creates a fresh, independent wrapper.