πͺ Functions: Closures and Callbacks
The Magic Backpack Story
Imagine you have a magic backpack. Every time you go into a room, you can take things from that room and put them in your backpack. Even after you leave the room, you still have those things!
Thatβs what closures are in JavaScript - functions that remember things from where they were born.
π Lexical Scope: Where Words Live
What is Lexical Scope?
Think of your house. You have:
- Your room (inner)
- The living room (outer)
- The whole house
Lexical scope means: Where you write your code decides what you can see.
const house = "My House";
function livingRoom() {
const sofa = "Comfy Sofa";
function myRoom() {
const toy = "Teddy Bear";
// I can see: toy, sofa, house
console.log(house); // β
Works!
console.log(sofa); // β
Works!
console.log(toy); // β
Works!
}
myRoom();
// console.log(toy); // β Can't see toy!
}
Simple Rule:
- Inner rooms can see outer rooms β
- Outer rooms cannot see inner rooms β
graph TD A["π Global: house"] --> B["ποΈ livingRoom: sofa"] B --> C["π§Έ myRoom: toy"] C -.-> |can see| B C -.-> |can see| A B -.-> |cannot see| C
β First-Class Functions: Functions Are VIPs
What Does First-Class Mean?
In JavaScript, functions are VIPs (Very Important Pieces of code). They can do anything a normal value can do!
Think of it like this: In some countries, anyone can become president. In JavaScript, functions can go anywhere values can go!
// 1. Store in a variable (like a toy in a box)
const sayHello = function() {
return "Hello!";
};
// 2. Put in an array (like toys in a basket)
const actions = [sayHello, function() {
return "Bye!"
}];
// 3. Put in an object (like a tool in a toolbox)
const robot = {
greet: function() {
return "Beep boop!";
}
};
// 4. Pass to another function
function doTwice(action) {
action();
action();
}
// 5. Return from a function
function createGreeter() {
return function() {
return "Hi there!";
};
}
π― Key Idea: Functions are just values. Treat them like numbers or strings!
π’ Higher-Order Functions: Functions That Boss Other Functions
What is a Higher-Order Function?
A higher-order function is like a manager:
- It takes workers (functions) and tells them what to do, OR
- It creates new workers (returns functions)
Real Life Example:
- A pizza shop (higher-order) takes chefs (functions) and makes pizza
- The shop doesnβt bake - the chefs do!
// Takes a function as input
function repeatThreeTimes(action) {
action();
action();
action();
}
repeatThreeTimes(function() {
console.log("Jump!");
});
// Output: Jump! Jump! Jump!
// Returns a function as output
function createMultiplier(number) {
return function(x) {
return x * number;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
Built-in Higher-Order Functions
JavaScript gives you powerful ones:
const numbers = [1, 2, 3, 4, 5];
// map: Transform each item
const doubled = numbers.map(function(n) {
return n * 2;
});
// [2, 4, 6, 8, 10]
// filter: Keep only some items
const bigOnes = numbers.filter(function(n) {
return n > 3;
});
// [4, 5]
// forEach: Do something with each
numbers.forEach(function(n) {
console.log(n);
});
π Callback Functions: βCall Me Back!β
What is a Callback?
Imagine ordering pizza:
- You call the pizza shop
- You give them your phone number
- They call you back when pizza is ready
A callback is a function you give to another function, saying βCall me back when youβre done!β
function orderPizza(callback) {
console.log("Making pizza...");
// When done, call back!
callback();
}
function celebrate() {
console.log("π Pizza is here! Yay!");
}
orderPizza(celebrate);
// Making pizza...
// π Pizza is here! Yay!
Why Use Callbacks?
1. Doing things in order:
function step1(next) {
console.log("Step 1: Wake up");
next();
}
function step2(next) {
console.log("Step 2: Brush teeth");
next();
}
function step3() {
console.log("Step 3: Eat breakfast");
}
step1(function() {
step2(step3);
});
2. Handling events:
// When button is clicked, run this
button.addEventListener("click", function() {
console.log("Button was clicked!");
});
3. Waiting for things:
setTimeout(function() {
console.log("2 seconds passed!");
}, 2000);
π Closures: The Magic Backpack
What is a Closure?
Remember our magic backpack? A closure is when a function remembers things from where it was created, even after leaving that place!
function createCounter() {
let count = 0; // This lives in the backpack!
return function() {
count = count + 1;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// count is hidden! No one else can touch it!
graph TD A["createCounter runs"] --> B["count = 0 created"] B --> C["Inner function returned"] C --> D["π Function carries count in backpack"] D --> E["Each call: count increases"]
Why Closures Are Magic
1. Private secrets:
function createBankAccount() {
let balance = 100; // Secret!
return {
deposit: function(amount) {
balance += amount;
return balance;
},
getBalance: function() {
return balance;
}
};
}
const myAccount = createBankAccount();
console.log(myAccount.getBalance()); // 100
console.log(myAccount.deposit(50)); // 150
// console.log(balance); // β Error! Can't access directly
2. Function factories:
function createGreeter(greeting) {
return function(name) {
return greeting + ", " + name + "!";
};
}
const sayHello = createGreeter("Hello");
const sayHola = createGreeter("Hola");
console.log(sayHello("Alice")); // Hello, Alice!
console.log(sayHola("Bob")); // Hola, Bob!
π― IIFE: Instant Action Functions
What is an IIFE?
IIFE = Immediately Invoked Function Expression
Itβs like a firework: You light it, and BOOM! It runs right away!
Normal function:
function rocket() {
console.log("π Blast off!");
}
rocket(); // You have to call it
IIFE:
(function() {
console.log("π Blast off!");
})();
// Runs immediately! No need to call it!
Breaking Down the IIFE
(function() {
// Your code here
})();
// Part 1: ( ... ) - Wrap in parentheses
// Part 2: function() { } - The function
// Part 3: () - Call it immediately!
Why Use IIFE?
1. Keep secrets safe:
(function() {
const secret = "I like cookies";
console.log(secret);
})();
// console.log(secret); // β Error! Secret is hidden!
2. Create instant tools:
const app = (function() {
let count = 0;
return {
add: function() {
count++;
return count;
},
get: function() {
return count;
}
};
})();
console.log(app.add()); // 1
console.log(app.add()); // 2
console.log(app.get()); // 2
3. IIFE with arrow functions:
(() => {
console.log("Arrow IIFE!");
})();
π§© Putting It All Together
Letβs see how everything connects:
// IIFE creates a private world
const gameScore = (function() {
// Lexical scope: score is visible inside
let score = 0;
// Higher-order function: takes callback
function onScoreChange(callback) {
// First-class: callback is a value
callback(score);
}
// Closure: remembers score
return {
add: function(points) {
score += points;
},
get: function() {
return score;
},
notify: onScoreChange
};
})();
gameScore.add(10);
gameScore.notify(function(s) {
console.log("Score is: " + s);
});
// Score is: 10
π¨ Quick Summary
| Concept | Think of it as⦠|
|---|---|
| Lexical Scope | Rooms in a house - inner sees outer |
| First-Class Functions | VIP guests - go anywhere |
| Higher-Order Functions | Managers - boss other functions |
| Callbacks | βCall me back when ready!β |
| Closures | Magic backpack - remembers things |
| IIFE | Firework - runs immediately |
π You Made It!
Now you understand the magic of JavaScript functions:
- Functions can see things from where they live (lexical scope)
- Functions are special values (first-class)
- Functions can control other functions (higher-order)
- Functions can wait and call back (callbacks)
- Functions can remember secrets (closures)
- Functions can run immediately (IIFE)
Youβre ready to build amazing things! π
