💡 Key Takeaways:

🔒 Encapsulation: Closures let functions “remember” variables from their outer scope.

🧠 Lexical Scope: Variables are stored in the scope where the function was defined, not where it’s called.

⚡ Persistent State: Closures allow functions to maintain state between calls.

🛠️ Best For: Private counters, factories, and event handlers that need remembered values.

🧠 What Is a Closure?

  • A function inside another function that remembers variables from its parent
  • Use for: data privacy, stateful functions, factory functions
  • Returns: the inner function with access to outer variables
function outer() {
  let count = 0;
  return function inner() {
    count++;
    return count;
  };
}

const counter = outer();
counter(); // 1
counter(); // 2

🔍 How It Works

  • Inner functions keep a reference to the outer scope
  • The outer function’s variables stay alive as long as the inner function exists
  • Useful for keeping data private and persistent
function greet(name) {
  return function() {
    console.log(`Hello, ${name}!`);
  };
}

const sayHi = greet('Ada');
sayHi(); // "Hello, Ada!"

🧩 Lexical Scope

  • Closures use lexical scope, meaning variables are found where functions are defined, not called
  • Use for: predictable access to outer data
  • Returns: values from outer scope correctly
const city = 'Paris';
function outer() {
  const city = 'London';
  return function inner() {
    console.log(city); // "London", not "Paris"
  };
}
outer()();

🔄 Common Use Cases

1️⃣ Private Variables

  • Hide internal state from outside access
  • Use for: counters, configuration, security
  • Returns: methods that can modify private data
function createCounter() {
  let count = 0;
  return {
    increment: () => ++count,
    get: () => count
  };
}

const c = createCounter();
c.increment(); // 1
c.get(); // 1

2️⃣ Function Factories

  • Create multiple similar functions sharing behavior
  • Use for: preconfigured callbacks or calculators
  • Returns: new functions with remembered values
function multiplier(x) {
  return n => n * x;
}

const double = multiplier(2);
double(5); // 10

3️⃣ Event Handlers

  • Capture variables in UI callbacks
  • Use for: remembering data when events trigger later
  • Returns: event function with preserved context
function setupButton(msg) {
  button.addEventListener('click', () => console.log(msg));
}

setupButton('Clicked!'); // remembers msg

4️⃣ Async Callbacks

  • Keep data alive across time delays
  • Use for: timeouts, promises, API results
  • Returns: function that can still access earlier values
function delayed(name) {
  setTimeout(() => console.log(`Hi ${name}`), 1000);
}
delayed('Sam'); // still remembers "Sam"

Disclaimer: The information provided on this website is for educational and informational purposes only. Health-related content is not intended to serve as medical advice, diagnosis, or treatment recommendations and should not replace consultation with qualified healthcare professionals. Financial content is for educational purposes only and does not constitute financial advice, investment recommendations, or professional financial planning services. Always consult with licensed healthcare providers for medical concerns and qualified financial advisors for personalized financial guidance.