Scope & Closure
Hey folks, here in this blog I am summarizing second part of You don’t Know JS book series. Which is Scope & Closure by Kyle Simpson.
Why not first? Because first part is only introduction of Programming, JS and briefs about what this book is going to cover. It’s like explaining A for Appple, B for Ball to a kid who is already in class 2.
Here in this blog I’ll cover all aspects of Scope and closure and after understating this blog thoroughly I promise you you’ll never struggle with weird behaviors of JS scope or variables.
Chapter 1. What is Scope?
Storing the value in a variable and retrieving the value out of that variable gives a program life (state) and the rules around storing and retrieving the value in/from variable is scope. To understand the setup process for these rules, which is scope, we need to understand compilation process.
Wait, JS is interpreted language, right? Nope.
JS isn’t compiled in advance like Java but it performs the same steps till the code generation in more sophisticated way. There are 3 steps in compilation process .
1. Tokenizing/Lexing :- It is process of breaking up a string of characters in meaningful tokens like var a = 10; will be broken in 5 tokens which are var, a, =, 10, and ;.
2. Parsing:- To understand the grammatical meaning of these tokens and relation of tokens with each other, these tokens have to be related to each other’s like family tree. For that Abstract Syntax Tree (AST) get created with nested elements. This whole process is Parsing.
3. Code-Generation: - The process of taking the AST and converting it into executable code.
JS engine is bit more complex. With all these 3 steps it performs the code optimization between parsing and code-generation which includes removing redundant variables and other elements.
For every single line of code, JS sees it as two statements. One that compiler will handle during execution and another that JS engine will handle during execution.
like for var a = 10;
When compiler goes through this line, compiler check the current scope for variable ‘a’ if ‘a’ isn’t present in scope compiler asks scope to create one variable with name ‘a’.
Then in second step compiler produce code to handle assignment operator.
For second step JS engine performs the look-Up to find the variable ‘a’ and assign value 10 to it. There are 2 types of look ups that JS engine has to perform to find the variable and assign value to it. LHS (left hand side) lookup and RHS (Right Hand side) lookup. LHS lookup is when variable is at left hand side of operator and RHS lookup is lookup of value of a variable.
Type of lookup is important because these look-ups behaves differently in circumstances where variable has not been declared. Like below example :-

Here for line b = a; JS engine is using LHS lookup. It’s assigning value ‘a’ to variable ‘b’ which is on left hand side of assignment operator. JS engine will search for variable ‘b’. JS engine will not find it anywhere so then global scope will create a new variable of name ‘b’ in global scope and hand it back to JS engine then JS engine assign value ‘a’ to that newly created variable ‘b’.
But if RHS lookup will fail to find the variable, as in line console.log(a, b) it’ll result in Reference error as it’ll not find that variable ‘b’ and will throw the error b isn’t defined.
Chapter 2. Lexical Scope
It is scope that is defined at lexing time, the time when JS engine breaks the string of characters into tokens, based on where variables and scope are authored.

Here the first bubble encompasses the global scope and only one identifier foo in it.
Second bubble encompasses the scope of foo with access of 3 identifier i.e; a, b, and bar()
Third bubble encompasses the scope of bar which has access to only one identifier c.
The bar is inside foo because we chose to define that inside foo. bar has access of all identifiers which is inside foo and foo has access of all identifiers which is inside global scope.
Scope look-up stops once it finds the first match for the variable. We can define variable at multiple layers of scope. That is called shadowing. But, scope look-up immediately stops once it finds the first match for the variable.
Scope look-up will start at innermost level and goes upwards until the first match. For example, in bar we are accessing c. JS engine will start look up for that variable and will access the first variable defined in scope of bar. So suppose even if c will be there in scope of foo JS engine will not go on looking for that variable in scope of foo since it has already accessed it from scope of bar. This phenomenon is shadowing.
So lexical scope is defined by where the function is declared and not by where and how it is invoked.
Chapter 3. Function Versus Block Scope
As we explored in previous section, scopes are nested inside each other which is defined at author time. And we only explored function-based scopes. But there are another structure in JS also which creates it’s own bubble, it’s own scope.
But before exploring other scope let’s dig a bit more about function scope.

Here in this code snippet, we have 3 scope bubble. Global, foo and bar. bar() has access of all the identifiers defined in global scope and scope of foo(), and scope of bar() itself. But foo() can not access the identifiers defined in scope of bar() and global scope can’t access the identifiers defined in scope of foo().
While this design can be quite useful, variable existing across the scope can lead to unexpected results without careful precautions.
- Principle of least privilege/least authority/least exposure :- In design of software, you should expose only what is minimally necessary and hide everything else. Which means any identifier which is not required in scope should not be accessible in that scope. For example :-

Here as we can see function doSomeThingElse() function and variable b is required only inside function doSomething() and not being used anywhere in global scope. so, it’s not a good practice to expose doSomethingElse() function and variable ‘b’ to global scope and polluting it unnecessarily. A better approach w ill be

2. Collision Avoidance :- It’s good to hide identifiers inside scope to avoid unintended collision with identifiers with same name in another scope with different use case.


To avoid collision, we can also create a object with unique name and then we can write all the properties and methods inside that uniquely named object.

But this(function foo) type of function introduces some problems. First, we declare a function using a name which pollutes the enclosing (global in this case) scope and then we have to call the function.
To overcome these two problems we can use immediately invoked function.

Here we are using function expression instead of function declaration.
What is function expression and function declaration you ask. Simply putting when word function is first word in line that is called function declaration otherwise function expression. Here first character is ‘(’ so this is function expression.
Here function foo is not bound in enclosing (global in this case) scope instead of it’s own enclosing scope and we didn’t have to call it explicitly.
To not to pollute enclosing scope we could have used anonymous function also. Like :-

But anonymous function has some drawbacks :-
- Anonymous function has no useful to display in stacktrace. which makes debugging difficult.
- It refer itself anonymous function has to use arguments.callee method which is deprecated.
- It’s not readable/understandable.
So it’s always better to use named function.
Block as Scope
While function is main unit of scope. Using block scope lead to even better, cleaner and maintainable code. It’s used to declare identifier as close as possible which extends least authority principle. It also avoids collision.

In this above example, there was no need to declare i variable in global or function scope and pollute them unnecessarily, so we declared inside loop.
Initially in JS we didn’t have any inbuilt mechanism for block scoping, but it changed with ES6. Now in JS, we have let and const which is used for block scoped variable and we can use var for function scoping.


Garbage Collection
Block scope is useful to garbage collection and in closure also to reclaim memory.

Here in this code, ideally after process() function someReallyBigData should have been garbage collected but since click function has closure over entire (global in this case) scope JS engine will still have access over someReallyBigData. To handle this we can write code like :-

So, we can say any variable declared within scope is attached to that scope.
Chapter 4. Hoisting
Consider the following line of code.

Since egg (declaration)comes before chicken (assignment). so compiler compiles this same code like

So here our output will be 2. So we can say, In JS variables and function declarations are moved from where they were in code to top of the code.

When compiler compiles this code it get’s

So, in a way calling function in both style is same and right.
While variable and functions both are hoisted we can’t say the same for function expressions.

Here variable foo is hoisted and attached to enclosing (global) scope so when in line number 1 we tried to access function foo it didn’t throw reference error because variable foo was there. It found foo while matching the type it found it was variable and not a function so line number 1 throws type error.
Chapter 5. Scope Closure
Now, we are very well aware of lexical scope so what are going to discover in this section is almost anticlimactic. That is closure.
So, what is closure? Closure is when a function is able to remember & access it’s lexical scope even if it that function is executing outside of it’s lexical scope.

Here bar function has lexical scope over outer function foo and variable a of foo is being used inside bar function. We are returning bar() from foo() assigning it into baz and baz() still have access to a.
We can see baz() is executing outside of foo but still have access of variable a of foo function. In this way, bar() is creating closure over foo().
Any of the various ways that functions can be passed around as values, and indeed invoked in other locations, are all examples of closure.
Be that timer, event handlers, AJAX requests, cross-window messaging, web worker or any of the synchronous/asynchronous tasks. Whenever we pass in callback function we can see closure.

Loops & Closures
Let’s say we need to write a code to print first 5 numbers after every second. So, We wrote like

Will that work? Let’s try…
ooh!! it printed 6, 6, 6, 6, 6 after every second. But we expected it to print 1, 2, 3, 4, 5.
What went wrong? As we know var is global variable. So when we wrote the for loop and declared variable i we declared that variable in global scope. And we are executing timer function after every i*1000 milliseconds. So, when we executed console.log(i) after i*1000 milliseconds i.e; 1 second value of i has already crossed 5 and became 6. We are running the timer function after every i*1000 seconds but every time console.log(i) access the same value of i from global scope which has become 6.
To prevent this and get desired result we can write code like :-

Here we created IIFE and assigning i to j. So every time we invoke that function we are creating a new variable altogether and assigning i to j. So now whenever our loop runs console statement starts with a fresh value of j printing 1, 2, 3, 4, 5.
or we can also use let variable here

Since let is block scope. Every time the loop is running it’s creating a new i variable in each block and setTimeout function is access the value of i from that same block. So every time console.log will get a new of i printing 1, 2, 3, 4, 5 after 1 seond of gap.
There are few code patterns that leverage the power of closure. Let’s explore more powerful of them. Which is Module Design Pattern.
There are 2 requirements of Module Design Pattern:-
- There must be an outer enclosing function. That must be called once.
- The enclosing function must return at least one inner function, so that inner function access over private scope and can access and modify that private scope.

here we have CoolModule with 2 private variables ‘something’ and ‘another’.
We are using these 2 variables in doSomeThing and doAnother methods and editing another variable in doAnother method and then returning an object with 2 objects having these 2 functions.
Here we are calling outer function CoolModule once and assigning it’s value to variable foo.
Inner function doSomething and doAnother has access of ‘something’ and ‘another’ (private value) of foo function and doAnother is also modifying the ‘another’ variable of foo function.
This pattern is Module Pattern. It is powerful tool that can help to improve the maintainability and reusability of JavaScript code. It helps in:-
Encapsulation:- It keeps code organized and maintainable by wrapping it in single object. Which prevents naming collision and makes it easier to change the code.
Performance:- The module pattern can improve performance by reducing the amount of code that is executed on the page. This is because the module pattern only loads the code that is needed for a particular function or feature.
That’s all about Second part i.e., Scope & Closure, of You Don’t Know JS series by Kyle Simpson. In this blog we covered all the 5 chapters of this book. Firstly we learnt what is Scope itself in first chapter then in second and third chapter we learnt about different types of scopes (lexical scope, function scope and block scope). In fourth and fifth chapter we learnt about behavior of scope (Hoisting & Closure) and how it works in JS.
I’ll cover third book of this series soon. If you liked this blog please give a few claps, write your suggestions below. Thank you!!