Mastering once(fn) in JavaScript

📌 Problem Statement

Implement a function once(fn) which accepts another function fn and returns a new function. This new function ensures that:

  • fn is executed only once, no matter how many times the new function is called.

  • On the first call, fn should run and return its result.

  • On subsequent calls, the function should return the result from the first call, without re-invoking fn.

✅ Input:

  • A function fn (can be sync or async)

  • The returned function can accept any number of arguments

✅ Output:

  • A function that runs fn once and returns the same result for all future calls.

🧠 Final Code Solution

function once(fn) {
  let called = false;
  let ans;

  return function (...args) {
    if (!called) {
      ans = fn.apply(this, args);
      called = true;
    }
    return ans;
  };
}

🔍Questions & Concepts

1. ❓ Why not call the function directly using fn(...args)?

Calling fn(...args) works only for pure functions. But if fn depends on this (like a method in an object), you’ll break the context. Using:

fn.apply(this, args);
  • Ensures correct this binding

  • Works with array-based arguments from ...args

It’s safer and more flexible in real-world scenarios.


2. ❓ What is the difference between call and apply?

MethodArguments FormatExample
callIndividual argumentsfn.call(this, arg1, arg2)
applyArguments as an arrayfn.apply(this, [arg1, arg2])

Since we’re using ...args which collects arguments into an array, apply() is the more natural choice.


3. ❓ What is a Higher-Order Function?

A higher-order function is one that:

  • Accepts another function as input

  • OR returns a function

In our case, once(fn) returns a function and wraps extra logic around fn, making it a classic higher-order utility.


4. ❓ What is a Closure?

Closures allow a function to remember and access its lexical scope even after the outer function has finished executing.

Here:

let called = false;
let ans;

These are preserved between invocations of the returned function. That’s how we remember if fn has been called and what it returned.


5. ❓ Real-Life Use Case: When is this Useful?

I used this pattern in a React app where I initialized an analytics SDK. To prevent duplicate initialization (even on re-renders), I wrapped the init() function inside once(). This ensured it ran only the first time.

Other Examples:

  • Preventing double form submissions

  • One-time event bindings (like addEventListener)

  • Lazy-loading external scripts

  • Showing modals/tooltips once


🧠 Wrap-Up

The once() function may look small, but it touches on major JavaScript concepts like closures, higher-order functions, and execution context.

Question Credit : https://namastedev.com/practice

10
Subscribe to my newsletter

Read articles from Gaurav Kumar Maurya directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Gaurav Kumar Maurya
Gaurav Kumar Maurya