Closure's wrap up aka "backpack" 
Tags: javascript, scope, functions
Published: 2021-03-27 13:16:22

Closure seems to be perceived as some kind of mysterious concept and is probably one of the most dreaded of all JS interview questions. For some part of the dev community at least. 

I am part of that part of the community. Since explaining sharpens understanding, then by way of an explanation I expect to clear some of that closure mystery. 

Closure is a form of space division or partition. That is the way I conceive of it. Since partition of space comes with rules of inclusion and exclusion, knowing those rules will help grasp closure. Scope is the first thing to examine.

# Scope

Scope can be looked at through two closely related angles. Scope as **space** and scope as **rules**. 

## Scope as space

[MDN](https://developer.mozilla.org/en-US/docs/Glossary/Scope) opens its definition of scope with the idea of space, in the form of context : 

>“The current context of execution. The context in which values and expressions are "visible" or can be referenced.”

Scope is an area where variables are visible, that is accessible to a function. As such, scope is a spatial relation between what can see and what can be seen. In other words, scope is a function’s visual field and that visual field is governed by rules. 

## Scope as rules

In the [*Scope and Closures*](https://www.oreilly.com/library/view/you-dont-know/9781449335571/index.html) volume of his *You Don’t Know JS* series, Kyle Sympson defines scope as the set of rules that governs the retrieval of variables in a computer program (*Scope and Closures*, 2014, p.11). Those rules guide both the compiler that produces executable code, and the programmer who writes the source code. 

Declaring a function that references a variable stored in a place where the compiler hasn’t been told to search means program failure. It is up to the programmer to follow the protocol.

If the programmer cannot change the protocol, it is the way he decides to write his code that determines the units of scope. That prerogative of the author of code is called lexical scoping. When lexical scoping applies, scope is set relatively to where a function is declared. That’s the programmer’s choice. It is not the only way that scope is set and some languages use dynamic scoping, which sets scope based on where variables are declared. That is to say, when the compiler looks for a variable’s value, it searches for what has been assigned to it most recently. 

```
let x = 2;
function foo(a) { return x + a }
function bar() { let x = 3; return foo(0) }
bar();
```

With lexical scoping, `bar()` would evaluate to 2. If JS had dynamic scoping, it would evaluate to 3. 

The rules of scope restrict the size the function’s visual field (or search area if we look at it through compiler eye). What is the visual field of a function made up of ? A function has access to its outer scope (including outer of outer etc) and its own inner scope, but not to other functions’ inner scopes (for example a sibling or child function, ie. the inner scope of functions that are either contained in outer scope or inner scope).

Going back to the previous program, `foo()` has access to `x = 2`, which is found in the outer scope. It does not however have access to `x = 3`, which is found in its sibling’s scope. 

When looking for a variable the compiler always starts looking in the inner scope of the function. If search fails there, the compiler will look in the outer scope, if it fails there, it will go to the outer scope of the outer scope and all the way up to the global scope, if needed. If nothing is found there, search stops since the global scope does not have an outer scope.

With dynamic scoping, when `foo()` is executed and the compiler needs to get the value assigned to a variable name, it will look for the most recent value assigned to that variable, which is 3.

Now is a good time to bring back the idea of context. The word “context” is a synonym of “surrounding”, and the idea of surrounding is at the heart of closure. 

# Closure

## Closure aliases

Closure has a few aliases, like Closed Over Variable Environment (C.O.V.E.), Persistent Lexical Scope Referenced Data (P.L.S.R.D.) or the “backpack” to name a few ([Will Sentance](http://willsentance.com/) coined the last one, and his [workshops](https://frontendmasters.com/teachers/will-sentance/) on Frontend Masters are incredibly useful and accessible). 

Even though they refer to the same thing, all three aliases focus on a different angle of the concept. C.O.V.E. emphasizes the enclosing process at play in a closure, P.L.S.R.D. focuses on the persistence of data and “backpack” underlines the idea that stuff is being carried around. 

That which is carried around is a variable environment or in other words, a piece of lexical scope. How does this happen ?

## Closure as a bundle/backpack

As was said earlier the rules of scope mean that a function has access to variables in the outer scope and its own inner scope, as long as those scopes do not belong to other functions’ inner scopes. Closure is the thing that makes it possible for a function that is executing outside of its original lexical environment to access all the variables of that environment (*Scope and Closures*, 2014, p. 48). Making it seem as though some inner scope is accessed from outer scope. For [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) a closure can be conceived as the 

>“combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment)”

Moreover, to close over a variable environment and make it persistent, a function has to be returned. 

## Some examples

### ReferenceError 

```
function tellSecret() { return secret }
function hideSecret() { 
let secret = “I ate all the cake”; 
tellSecret(secret) 
}
hideSecret(); // ReferenceError: secret is not defined

```
This is how you would expect things to work. Invoking `hideSecret()` throws a ReferenceError, since `tellSecret()`, which is called from the inner scope, references a variable `secret` as parameter that is nowhere to be found in its outer or inner scope. Sure that variable is sitting right next to it in `hideSecret`’s inner scope, but `tellSecret` does not have access to its sibling’s inner scope.

### Truth comes out 

```
function hideSecret() { 
  let secret = “I ate all the cake”; 
  return function needToSay() { 
    return secret; 
    }
 }
let tellSecret = hideSecret();
tellSecret(); // “I ate all the cake”
```
When a function is executed, it is pushed onto the call stack and a new execution context is created. Within that execution context, variables are accessible following the rules of scope. When execution reaches a return statement or the bottom of the function, it is popped off the stack and the execution context is erased. The variable environment enclosed in the function’s inner scope vanishes. However, with closure, that variable environment persists. That is what happens above.

The return value of `hideSecret()` is assigned to a variable called `tellSecret`. That return value is `needToSay`’s function declaration. When slapping a pair of parentheses at the end of `tellSecret`, it is the code inside of `needToSay` that is being executed, bundled together with its lexical environment. The value of `secret` is being returned, which is nowhere to be found in global scope. Even if `hideSecret` has been popped off the call stack, by returning `needToSay`, a record has been made of that lexical environment, and that is closure. 

### One thing and the other 

```
function tellSecret(cb) { 
  let secret = " I did NOT eat the cake"; 
  return cb(secret); 
}
function hideSecret() { 
  let secret = "I ate all the cake";
  function sayOneThing(a) { 
    return function sayAnother(b) { 
      return a + " " + b;
    }
  } 
  return tellSecret(sayOneThing(secret)); 
}
let s = hideSecret(); 
s(); // "I ate all the cake  I did NOT eat the cake"

```

First `tellSecret` is declared, then `hideSecret` and then the return value of `hideSecret` is assigned to the variable `s`. What does `hideSecret` return ? It returns a call to `tellSecret`, with the function `sayOneThing` passed as parameter. So `hideSecret` should return whatever `tellSecret` returns. What does the call to `tellSecret` evaluate to ? The return value of `tellSecret` will be whatever the function that is passed as parameter returns. So `tellSecret` should return whatever `sayOneThing` returns. What does `sayOneThing` return ? The return value of `sayOneThing` is the definition of a function called `sayAnother`. So invoking `s` amounts to calling `sayAnother`, and `sayAnother` returns the concatenation of whatever parameter was passed in `sayOneThing` (“I ate all the cake”) and `sayAnother` (“I did NOT eat the cake”). It is because `sayAnother` is bundled with a record of `sayOneThing`’s lexical environment that it can return a variable from an execution context that looks as though it’s gone. That is what closure is. 

I think.