πŸ“˜ JavaScript Closures

βœ… 1. What is a Closure?

A closure is created when a function:

  • Accesses variables from an outer scope, even after that scope has finished executing.

πŸ’‘ In simple terms:
A function remembers the variables around it, even if it’s run later.


πŸ“Œ 2. Basic Closure Example

jsCopyEditfunction outer() {
  const name = "Alice";

  function inner() {
    console.log("Hello, " + name); // βœ… Has access to `name`
  }

  return inner;
}

const greet = outer(); // outer() runs and returns `inner`
greet(); // Hello, Alice

Even though outer() has finished, inner() still has access to name. That’s a closure.


πŸ“Œ 3. Closures Keep Private Data

jsCopyEditfunction createCounter() {
  let count = 0;

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

const counter = createCounter();

console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

βœ… count is private β€” only the returned function can access it.


πŸ“Œ 4. Closures in Loops (Classic Mistake)

Without closure:

jsCopyEditfor (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// Output: 3, 3, 3 (not 0, 1, 2)

βœ… With closure using let (block scope):

jsCopyEditfor (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// Output: 0, 1, 2

πŸ“Œ 5. Real-World Use: Encapsulation

jsCopyEditfunction bankAccount(initialBalance) {
  let balance = initialBalance;

  return {
    deposit(amount) {
      balance += amount;
    },
    withdraw(amount) {
      balance -= amount;
    },
    getBalance() {
      return balance;
    }
  };
}

const myAccount = bankAccount(100);
myAccount.deposit(50);
console.log(myAccount.getBalance()); // 150

βœ… balance is not accessible from outside β€” only through methods.


πŸ“Œ 6. Closures in Event Listeners

jsCopyEditfunction setupButton(label) {
  let count = 0;

  return function clickHandler() {
    count++;
    console.log(`${label} clicked ${count} times`);
  };
}

const saveHandler = setupButton("Save");

document.getElementById("saveBtn").addEventListener("click", saveHandler);

🧠 Summary Table

FeatureDescription
ClosureInner function accesses outer function variables
Data PrivacyVariables remain hidden from outside scope
Persistent MemoryData sticks around after outer function runs
Common Use CasesCounters, modules, callbacks, event handlers

πŸ§ͺ Practice Challenges

  1. Write a secretHolder(secret) function that returns getSecret() and setSecret(newSecret).
  2. Create a makeMultiplier(factor) that returns a function to multiply any number by that factor.

πŸ“Œ Bonus: Visualizing Closure

jsCopyEditfunction outer() {
  let message = "I'm inside outer";

  return function inner() {
    console.log(message);
  };
}

const fn = outer(); // outer() returns inner
fn(); // logs: I'm inside outer

Even though outer() is done, inner() remembers message.


Would you like this as:

  • πŸ“„ A printable PDF?
  • πŸ’» A live JSFiddle with interactive closure examples?
  • 🧠 A mini quiz to test your understanding?