JavaScript Closures Explained

Introduction

Closures are one of the most important concepts in JavaScript. They allow inner functions to access variables from their outer function — even after the outer function is finished executing.

1. Basic Closure Example

function outer() {
  let x = 10;

  function inner() {
    console.log(x); // still remembers x
  }

  return inner;
}

const fn = outer();
fn(); // prints 10
    

2. Closures Remember Their Scope

function counter() {
  let n = 0;

  return function() {
    n++;
    console.log(n);
  }
}

const c = counter();
c(); // 1
c(); // 2
c(); // 3
    

3. Closure With Parameters

function makeAdder(a) {
  return function(b) {
    return a + b;
  }
}

const add5 = makeAdder(5);
console.log(add5(3)); // 8
    

4. Closures in Loops

Classic bug without closure:

for (var i = 1; i <= 3; i++) {
  setTimeout(() => console.log(i), 1000);
}

// prints: 4,4,4
    

Fixed with closures (let):

for (let i = 1; i <= 3; i++) {
  setTimeout(() => console.log(i), 1000);
}
    

5. Private Variables Using Closures

function bankAccount() {
  let balance = 0;

  return {
    deposit(x) { balance += x; },
    getBalance() { return balance; }
  };
}

const acc = bankAccount();
acc.deposit(50);
console.log(acc.getBalance()); // 50
    

6. Closures for Module Pattern

const Settings = (function(){
  let theme = "dark";

  return {
    getTheme(){ return theme; },
    setTheme(t){ theme = t; }
  };
})();

Settings.setTheme("light");
console.log(Settings.getTheme());
    

7. Event Handlers With Closures

function makeHandler(msg) {
  return () => console.log(msg);
}

button.addEventListener("click", makeHandler("Clicked!"));
    

8. Factory Functions Use Closures

function createUser(name) {
  return {
    say() { console.log("Hi, I'm " + name); }
  };
}

createUser("Kaloyan").say();
    

9. Why Closures Matter

10. Summary