What are Scopes, Lexical Environment and Closures in Javascript?
Table of contents
The closure is one of the most important concepts in Javascript and my favorite too. In this blog, we are going to understand closures in a beginner-friendly manner. Before knowing about closures we need to understand what is lexical environment and in order to understand the lexical environment, we need to understand scopes.
What is Scope?
Scope means where you can access a specific variable or function in our code. It is a boundary within which you can access variables and functions. The nature of scope is, that accessibility is always flowing like a water from top to bottom, not bottom to top. There are two ways of knowing the scope.
One is what is the scope of a variable? This question gives the answer to where you can access a specific variable in a given code.
Is variable inside the scope? This question helps us understand the accessibility of a specific variable.
There are three types of scopes in Javascript. They are
Global scope Block scope Function scope Global Scope: you can access this globally scoped variable anywhere in the code
Block Scope: variables inside curly braces are accessible only inside that block, it is not available outside. Note that (var variables exist throughout the function they’re declared in (or globally if declared globally), they aren’t confined to the block they’re in)
Function Scope: variables inside the function are accessible only inside that function, it is not available outside
What is a lexical environment?
The lexical environment is directly dependent on scope and vice versa. Along with execution context, a lexical environment is created. The lexical environment contains local memory along with reference to the memory of its lexical parent. When the execution line touches line number 7, variables a and b need to be logged in the console so the search begins. It will find the variable b inside its own function itself but a is not present inside c so it will go to its lexical parent memory through this keyword and check for variable a and it will find it
In the above visual, we can see that whenever a function is invoked a new execution context is created along with this reference. Where this keyword refers to the memory of its lexical parent. So the combination of both local memory with the memory of its parent is known as the lexical environment.
Closures
Here comes our hero.
The variables inside the function can’t be accessed from outside of it, it’s obvious.
In the above code, if we uncomment the line number 10 and execute we will get a reference saying that x is not defined. But implicitly we are trying to access x by calling the func1 function. Does it throws an error or does it work?
We were surprised to discover that it works and logs x in the console. This is possible only because of closures. Let us explore how this is possible.
A simple definition of Closure is the binding of a function to its lexical environment. Function with its lexical scope is called closures.
Function a returns function b with its lexical environment to variable func1. Inside function b it forms a closure with variables of a. In other words, function b is binded to the variables of function a
A closure is a combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time. — mdn
We can see that func1 contains a reference to the closure of a, and to the same function itself, and to global this.
Conclusion
In the end, it is obvious that closures are very important. Asynchronous jobs are possible because of closure due to the fact that most APIs require callback functions.
Subscribe to my newsletter
Read articles from vigneshwaran R directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by