Advanced Functions
A closure happens when an inner function remembers variables from the outer function, even after the outer function has finished.
Closures
A closure happens when an inner function remembers variables from the outer function, even after the outer function has finished.
This is useful for private data, counters, and factory functions.
Real-life example: A bank locker keeps your items safe inside. Only your key (inner function) can open it — outsiders cannot see what is inside.
function makeCounter(start = 0) {
let count = start; // "private" — not visible outside
return {
add() { count++; return count; },
get() { return count; },
};
}
const score = makeCounter(10);
score.add(); // 11
score.add(); // 12
// score.count — undefined (protected)Callbacks
A callback is a function you pass to another function. It runs later — after a click, a timer, or when data arrives.
Real-life example: You order food and give your phone number (callback). The restaurant calls you when the order is ready — you do not stand at the counter forever.
function showMessage(message, callback) {
console.log(message);
callback();
}
document.querySelector("#btn").addEventListener("click", () => {
showMessage("Lesson saved!", () => {
alert("Great job on Rishtaara!");
});
});Rest and spread parameters
Rest (...args) collects extra arguments into an array. Spread (...arr) expands an array or object into separate items.
Real-life example: Rest is like putting loose coins into one pouch. Spread is like pouring that pouch back out onto the table one coin at a time.
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
sum(2, 3, 5); // 10
const scores = [85, 92, 78];
const allScores = [70, ...scores, 95]; // [70, 85, 92, 78, 95]
const user = { name: "Asha", grade: 10 };
const updated = { ...user, grade: 11 }; // clone + change one fieldIIFE (Immediately Invoked Function Expression)
An IIFE is a function that runs right away. It creates its own scope so variables do not leak into the global space.
Modern code uses modules instead, but you will still see IIFEs in older scripts.
Real-life example: A pop-up stall opens, sells snacks, and closes — all in one day. It does its job once and leaves no mess behind.
(function () {
const secretKey = "abc123";
console.log("App started with key:", secretKey);
})();
// secretKey is not available here — good for avoiding name clashesHigher-order functions
A higher-order function takes another function as an argument, returns a function, or both. Array methods like map, filter, and reduce are higher-order functions.
Real-life example: A teacher (higher-order function) gives homework to students (functions). The teacher decides when and how each student works.
const prices = [100, 250, 80];
const withTax = prices.map(p => p * 1.18);
const bigOnes = prices.filter(p => p >= 100);
const total = prices.reduce((sum, p) => sum + p, 0);
console.log(withTax); // [118, 295, 94.4]
console.log(bigOnes); // [100, 250]
console.log(total); // 430call, apply, and bind (brief)
These methods control what this points to inside a function. call and apply run the function right away; bind returns a new function with this fixed.
Real-life example: Borrowing a friend's bike (call/apply) means you ride it today with their name on the register. bind is like getting a spare key — same bike, same owner, ready anytime.
const person = {
name: "Ravi",
greet(greeting) {
console.log(`${greeting}, ${this.name}`);
},
};
const other = { name: "Sita" };
person.greet.call(other, "Hello"); // Hello, Sita
person.greet.apply(other, ["Hi"]); // Hi, Sita
const greetSita = person.greet.bind(other);
greetSita("Namaste"); // Namaste, Sita