Global scopestepmakeCounterƒnextmakeCounter() scopecountnext() call scopeno variablesƒ1const step = 1;2function makeCounter() {3 let count = 0;4 return function () {5 count = count + step;6 return count;7 };8}9const next = makeCounter();10next();11console.log(next());Console2counter.js:11ƒ011122
Back: three scopes (boxes of variables) and the outer links between themMiddle and front: the function and its [[Environment]] link, the program counter.js, the consoleTokens: instructions, a lookup that walks outward, and the values 0, 1 and 2At the back, three scopes as trays: the global scope, the scope made by the call makeCounter(), and the scope of a next() call. The traces between them are the outer links a lookup follows, inward box to outer box. The function made on line 4 keeps a link to the makeCounter() scope, so that scope stays after its call ends, and count survives from one call of next() to the next. The boxes are what the ECMAScript specification calls Environment Records. Each has an outer link ([[OuterEnv]]); a function call's record is made by NewFunctionEnvironment, and its outer link is the function's [[Environment]].

What scope is

  1. Scope is the part of a program where a name can be used. Every function call gets its own scope, a box of variables. Code sees names in its own box and in the boxes outside it, never inside.

Making a closure

Calling the closure

Why it matters

What happens

// step 1/10 · scope
scope        where a name can be used
global       names at the top level of the script
function     every CALL gets a new box of its own
block        let and const inside { } (not used here)
lookup       own box first, then outward, never inward

The boxes are what the ECMAScript specification calls Environment Records. Each has an outer link ([[OuterEnv]]); a function call's record is made by NewFunctionEnvironment, and its outer link is the function's [[Environment]]. JavaScript has no command to free memory. A garbage collector removes values that can no longer be reached; when it runs is up to the engine. Engines may also keep only the variables a closure actually uses.