Topic 04 / 15
Functions, Scope & Closures
Three Ways to Write a Function
// 1. Declaration — hoisted (usable before its definition)
function add(a, b) {
return a + b;
}
// 2. Function expression
const subtract = function (a, b) {
return a - b;
};
// 3. Arrow function — the modern default
const multiply = (a, b) => a * b; // implicit return
const square = n => n * n; // one param, no parens needed
const greet = (name) => {
const msg = `Hello ${name}`; // braces = explicit return
return msg;
};Arrows are shorter and — crucially — don’t have their own this (they inherit it from the surrounding scope). That makes them ideal for callbacks; we’ll revisit this in the classes topic.
Default, Rest & Spread
function connect(host, port = 5432) { ... } // default parameter
function sum(...nums) { // rest — gathers into an array
return nums.reduce((acc, n) => acc + n, 0);
}
sum(1, 2, 3); // 6
const nums = [1, 2, 3];
Math.max(...nums); // spread — unpacks an array into argumentsFunctions Are Values
Pass them, return them, store them — this is the heart of JS:
const byScore = (a, b) => b.score - a.score;
players.sort(byScore);
setTimeout(() => console.log("2s later"), 2000); // callbackScope
let/const are block-scoped — they exist only inside the nearest { }:
if (true) {
const secret = 42;
}
console.log(secret); // ReferenceErrorInner scopes can read outer variables. That plus first-class functions gives us…
Closures — Functions That Remember
A closure is a function that captures variables from the scope where it was created — and keeps them alive after that scope returns:
function makeCounter() {
let count = 0; // private — nothing outside can touch it
return function () {
count++;
return count;
};
}
const counter = makeCounter();
counter(); // 1
counter(); // 2
const другой = makeCounter();
другой(); // 1 — each call gets its OWN countClosures power debounce, event handlers, module patterns, React hooks — most of practical JS:
function debounce(fn, delay) {
let timer; // remembered between calls
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}
const onType = debounce(() => search(input.value), 300);If you can explain makeCounter from memory, you understand closures — a guaranteed interview question.