Skip to main content

Command Palette

Search for a command to run...

Closure

Published
3 min readView as Markdown

🔹 What is a Closure?

A closure is created when a function remembers the variables from its outer scope even after that outer function has finished executing.

👉 In simple words:
Inner functions can access variables of their outer function even after the outer function has returned.


Example 1: Basic Closure

function outer() {
  let count = 0;  // outer variable

  function inner() {
    count++;  // inner function using outer variable
    return count;
  }

  return inner;
}

const counter = outer();  
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

✅ Even though outer() finished executing, the inner() function still remembers count.
That’s a closure!


🔹 Why Closures are Useful?

  1. Data privacy (variables hidden from outside)

  2. Stateful functions (functions that “remember” things)

  3. Callbacks & Event Listeners

  4. Module pattern (imitating private methods in JS)


🔹 10 Problems on Closures (with Solutions)


Problem 1: Counter Function

Create a function that counts how many times it has been called.

function createCounter() {
  let count = 0;

  return function() {
    count++;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

Problem 2: Private Variable

Make a variable private so it cannot be accessed directly.

function secretHolder(secret) {
  return {
    getSecret: function() {
      return secret;
    },
    setSecret: function(newSecret) {
      secret = newSecret;
    }
  };
}

const holder = secretHolder("abc123");
console.log(holder.getSecret()); // abc123
holder.setSecret("newSecret");
console.log(holder.getSecret()); // newSecret

Problem 3: Multiplication Factory

Make a function that returns another function which multiplies numbers.

function multiplier(x) {
  return function(y) {
    return x * y;
  };
}

const double = multiplier(2);
console.log(double(5)); // 10
const triple = multiplier(3);
console.log(triple(5)); // 15

Problem 4: Remember Me

Create a function that remembers a name.

function rememberName(name) {
  return function() {
    return "Hello, " + name;
  };
}

const greetAmit = rememberName("Amit");
console.log(greetAmit()); // Hello, Amit

Problem 5: Event Listener with Closure

Closures allow us to remember data inside event listeners.

function attachEvent() {
  let count = 0;
  document.getElementById("btn").addEventListener("click", function() {
    count++;
    console.log("Button clicked " + count + " times");
  });
}
attachEvent();

Problem 6: Delay Logger

Print numbers 1 to 5 with setTimeout.

❌ Common mistake:

for (var i = 1; i <= 5; i++) {
  setTimeout(() => console.log(i), 1000);
}
// Prints 6 five times

✅ Solution using closure:

for (var i = 1; i <= 5; i++) {
  (function(n) {
    setTimeout(() => console.log(n), 1000 * n);
  })(i);
}
// Prints 1, 2, 3, 4, 5

Problem 7: Create ID Generator

Every time you call, you get a new ID.

function idGenerator() {
  let id = 0;
  return function() {
    id++;
    return "ID-" + id;
  };
}

const generate = idGenerator();
console.log(generate()); // ID-1
console.log(generate()); // ID-2

Problem 8: Only Once Function

Function should only run once.

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

  return function(...args) {
    if (!called) {
      result = fn(...args);
      called = true;
    }
    return result;
  };
}

const sayHello = once(() => "Hello");
console.log(sayHello()); // Hello
console.log(sayHello()); // Hello (still)

Problem 9: Caching / Memoization

Closures help cache results.

function memoize(fn) {
  let cache = {};

  return function(x) {
    if (cache[x] !== undefined) {
      return "From cache: " + cache[x];
    }
    let result = fn(x);
    cache[x] = result;
    return "Calculated: " + result;
  };
}

const square = memoize(n => n * n);
console.log(square(4)); // Calculated: 16
console.log(square(4)); // From cache: 16

Problem 10: Module Pattern

Closures help simulate private methods.

const BankAccount = (function() {
  let balance = 0;

  return {
    deposit: function(amount) {
      balance += amount;
      return balance;
    },
    withdraw: function(amount) {
      if (amount <= balance) {
        balance -= amount;
        return balance;
      }
      return "Insufficient funds";
    },
    getBalance: function() {
      return balance;
    }
  };
})();

console.log(BankAccount.deposit(100)); // 100
console.log(BankAccount.withdraw(30)); // 70
console.log(BankAccount.getBalance()); // 70

More from this blog

Amit singh's blog

235 posts