Module lessons (4/4)
Closures and scope
A closure is a function that "remembers" the variables of the scope in which it was defined, even after that scope has ended. It looks like magic but it's a direct consequence of the scope rules.
Scope chain
A function can read variables declared outside itself, walking up the chain of scopes:
const moltiplicatore = 10;
function moltiplicaPer10(n) {
return n * moltiplicatore; // reads from the closure
}
moltiplicaPer10(3); // 30Function factory
The most typical pattern: a function that returns another function, "customized" with the parameters it received.
function creaSaluto(prefisso) {
return function (nome) {
return `${prefisso}, ${nome}!`;
};
}
const ciao = creaSaluto('Ciao');
const buongiorno = creaSaluto('Buongiorno');
ciao('Anna'); // 'Ciao, Anna!'
buongiorno('Marco'); // 'Buongiorno, Marco!'Each call to creaSaluto creates a separate scope, with its own prefisso.
Counter with private state
The classic example: a closure that keeps a counter without exposing it to the outside.
function creaContatore() {
let n = 0;
return function () {
n++;
return n;
};
}
const c = creaContatore();
c(); // 1
c(); // 2
c(); // 3
const c2 = creaContatore();
c2(); // 1 ← isolated state!n is private: no one outside the closure can read or modify it.
Try it
Implement a factory `makeCounter()` that returns a function: each call of the function returns a progressive integer starting from 1. Different counters must be independent.
Show hint
Declare n with let inside makeCounter, then return a function that does ++n.
Solution available after 3 attempts
Review exercise
Implement `makeAdderWith(base)` that returns a function: given a number n, it returns base + n. Each adder remembers its own base.
Show hint
return an arrow function that uses base from the outer parameter.
Solution available after 3 attempts