As defined by MDN documentation:
But what does that mean exactly?
- If the variable is declared globally (for example; at the top of our .js document, outside any other function).
- If the variable is declared within that function itself, thus making it a private variable that only that one function can access.
- If the variable is declared inside the function’s “parent” or “outer” function.
As you can see, our global variable
bakedGoods is accessible from each function.
Our last function
goToStore() contains an inner function called
makePurchase(). Our inner function has access to all the variables declared within its parent,
goToStore(). This is what the documentation refers to as lexical scoping. Notice in our
goToStore() function we didn’t execute the inner function but merely returned it. What happens if we try to execute that parent function? Will
makePurchase() still know about
goToStore ‘s variable?
Yes! The reason is because of closure. A closure is an inner function that remembers its ‘lexical environment’. Meaning that it’s a function that never forgets the conditions or context in which it was created and thus will always remember its parent functions variables.
Every closure has three scopes:
- Local scope, meaning it can access any variables assigned within itself
- The scope of its outer/parent function
- Global scope
The great thing about closures is that they give us access to variables even once the function has finished executing.
Where things start to get tricky is when we try to implement closures inside of a loop. For example, if we were to use
var to assign a variable in this loop:
We might expect these loops to print out the phrase “ — — are my favorite animal” with each animal inserted as the first word of the sentence. However, if we try this out in our console, we see that we just get the phrase “Monkeys are my favorite animals.” We create four closure functions, each one sharing the same lexical scope with a variable
animal. However, the loop has already run its course by the time we get to our closure, which is why we only see our last phrase printed in the console. There are two ways to solve this problem.
The first way is to use another closure!
What this does is bind the variable within each function to a separate, unchanging value outside of the function.
In this particular instance, however, having a closure isn’t incredibly advantageous. The most elegant option for us might be to ditch our closure entirely and just loop through the array, printing the phrase for each animal.
Closures can provide us with elegant ways to access what might otherwise be private variables in our code.