Closures in JavaScript
Inner function keeps the outer variables. That counter example is the whole point.
IntermediateFunction ProgramsExample 3 of 3
closures.js
1// Closure: Function has access to outer function's variables23// Example 1: Basic closure4function outerFunction(x) {5 // Outer function's variable6 let outerVar = x;78 // Inner function (closure)9 function innerFunction(y) {10 console.log("Outer:", outerVar, "Inner:", y);11 return outerVar + y;12 }1314 return innerFunction;15}1617let closure = outerFunction(10);18console.log("Result:", closure(5));1920// Example 2: Counter using closure21function createCounter() {22 let count = 0;2324 return function() {25 count++;26 return count;27 };28}2930let counter1 = createCounter();31let counter2 = createCounter();3233console.log("\nCounter 1:", counter1());34console.log("Counter 1:", counter1());35console.log("Counter 2:", counter2());36console.log("Counter 1:", counter1());3738// Example 3: Private variables39function createBankAccount(initialBalance) {40 let balance = initialBalance; // Private variable4142 return {43 deposit: function(amount) {44 balance += amount;45 return balance;46 },47 withdraw: function(amount) {48 if (amount <= balance) {49 balance -= amount;50 return balance;51 } else {52 return "Insufficient funds";53 }54 },55 getBalance: function() {56 return balance;57 }58 };59}6061let account = createBankAccount(100);62console.log("\nInitial balance:", account.getBalance());63console.log("After deposit 50:", account.deposit(50));64console.log("After withdraw 30:", account.withdraw(30));65console.log("Final balance:", account.getBalance());6667// Example 4: Function factory68function createMultiplier(multiplier) {69 return function(number) {70 return number * multiplier;71 };72}7374let double = createMultiplier(2);75let triple = createMultiplier(3);7677console.log("\nDouble 5:", double(5));78console.log("Triple 5:", triple(5));7980// Example 5: Closure with loop (common mistake)81console.log("\nClosure in loop:");82for (var i = 0; i < 3; i++) {83 setTimeout(function() {84 console.log("var i:", i); // Prints 3, 3, 385 }, 100);86}8788// Solution: Use let89for (let j = 0; j < 3; j++) {90 setTimeout(function() {91 console.log("let j:", j); // Prints 0, 1, 292 }, 200);93}
Output
Outer: 10 Inner: 5 Result: 15 Counter 1: 1 Counter 1: 2 Counter 2: 1 Counter 1: 3 Initial balance: 100 After deposit 50: 150 After withdraw 30: 120 Final balance: 120 Double 5: 10 Triple 5: 15 Closure in loop: var i: 3 var i: 3 var i: 3 let j: 0 let j: 1 let j: 2
What's going on
A function returned from another function still sees the outer lets. The bag stays.
Loop plus var plus closure: all callbacks share one i. let fixes it. That interview question.