Functions That Remember
First, a word about scope. The scope of a variable is the part of the code where you can use it. A variable made with let or const exists from its declaration to the end of its block, the closing curly brace. Parameters belong to their function. Code inside a block can see variables from outside it, but code outside cannot see in:
function setup() {
const secret = 42;
console.log(secret);
}
setup();
console.log(secret);
Output:
42
/box/index.js:7
console.log(secret);
^
ReferenceError: secret is not defined
at Object.<anonymous> (/box/index.js:7:13)
Inside setup, secret works. Outside, it does not exist. This is useful: two functions can each have a variable called total, and they never get mixed up.
Now the surprising part. A function can use variables from the place where it was created, and it keeps them even after that place has finished running:
function makeCounter() {
let count = 0;
return () => {
count++;
return count;
};
}
const clicks = makeCounter();
console.log(clicks());
console.log(clicks());
console.log(clicks());
const pageViews = makeCounter();
console.log(pageViews());
Output:
1
2
3
1
Follow what happens. makeCounter runs, creates count, returns an arrow function, and ends. You might expect count to be gone now. But each call to clicks() adds 1 to it, and the value is kept between calls. The returned function holds on to the variables of the place where it was created. As long as that function exists, those variables stay alive. A function together with the variables it keeps is called a closure.
Now look at the last line. pageViews() prints 1, not 4. Each call to makeCounter() creates a new count, and each returned function keeps its own. So there are two counters, and they do not affect each other.
Closures give you private data. No code outside can read or change count, except by calling the function. You will meet closures often, because any function that uses a variable from the code around it is a closure. Callbacks and timers in the Async section depend on this.
In the exercise, complete makeCounter so that each counter it makes keeps its own count.