FrontendAtlas
Interview Questions
Home>JavaScript interview questions> JavaScript coding challenges >Once (Function Wrapper)

Once (Function Wrapper)

easy
By FrontendAtlas Editorial · Updated Jan 30, 2026
Implement once(fn) that returns a wrapper which executes fn only on the first call. Cache and return the result on subsequent calls without re-invoking fn. This tests closures, memoization, and side-effect control. Concepts: higher-order, functions, closure.

Arguments

  • fn: Function — The function to call once.

Returns

Function — A wrapped function that only calls fn once.
Examples
const addOnce = once((a, b) => a + b);
addOnce(1, 2); // 3
addOnce(5, 6); // still 3

const obj = { x: 2, get: once(function (n) { return this.x + n; }) };
obj.get(3); // 5

Solution

Overview

Wrap a function with a closure that tracks whether it has been called and stores its return value. The first call executes the original function; every later call returns the cached result. This pattern is common for one-time initialization and idempotent setup. Key concepts: higher-order, functions, closure.

1

Approach: Closure with a called flag

Algorithm:

  • Create called = false and result in the outer scope.
  • Return a wrapper function that checks called.
  • If not called, invoke fn with the current arguments/this, store the result, and set called = true.
  • Always return result.

Complexity: O(1) per call, O(1) extra space.

export default function once(fn) {
  let called = false;
  let result;
  return function (...args) {
    if (!called) {
      called = true;
      result = fn.apply(this, args);
    }
    return result;
  };
}
export default function once<F extends (...args: any[]) => any>(fn: F): F {
  let called = false;
  let result: ReturnType<F>;
  return function (this: any, ...args: Parameters<F>) {
    if (!called) {
      called = true;
      result = fn.apply(this, args);
    }
    return result;
  } as F;
}

Notes & Pitfalls

Pitfalls
  • Preserve `this` by using `fn.apply(this, args)`.
  • Subsequent calls return the first result, even with different arguments.
  • If `fn` throws, this implementation still marks it as called.
Edge cases
  • Functions that return `undefined` still count as called.
  • Wrapper should work with any number of arguments.
Techniques
  • Closures for private state.
  • Higher-order functions.

Common mistakes on this challenge

  • Once wrapper should cache first result and stop re-invocation

    The wrapped function should execute exactly once with stable return value thereafter.

    • Store `called` flag and cached `result` in closure state.
    • Invoke underlying function only on first call and cache the output.
    • Use `fn.apply(this, args)` to preserve call-site context.

Resources

  • MDN – Closures
  • MDN – Function.prototype.apply()

Similar questions

Curry FunctionintermediateCreate a Counter FunctioneasyCreate a Spy Function (Test Double)intermediate

Guides

Frontend interview preparation guideGuideFrontend coding interview questions and prep guideBlueprintJavaScript Problems That Actually Show UpBlueprintBuild Great UI in 60 MinutesBlueprint

Preparing for interviews? Use Frontend Coding Challenges first, then move into a concrete Study Plan before targeted Company Prep.

Open frontend interview questionsBrowse JavaScript interview questionsOpen Essential 60Open Machine Coding HubOpen Frontend Coding ChallengesOpen System DesignOpen Interview Prep GuideOpen System Design BlueprintOpen Framework Prep PathsOpen Study PlansOpen JavaScript mastery study planOpen Company PrepOpen JavaScript Framework Prep Guide
↗Incidents hub
62 / 88Next →→