Scopes in Javascript
Are you having a difficult time understanding scopes in javascript then this blog is for you here I will explain to you all about scopes in javascript. After reading this whole post I am damn sure you will surely master scopes in javascript.
Before understanding scopes, let's understand few core concepts of javascript that are related to scopes.
Execution Context
Let's see the example to understand more clearly.
This is a simple code which print return my name. But this is the best example to understand execution context. Each time a function is called an execution context is created Like below
Whenever javascript sees the these () bracket that is an invocation of the function it creates an execution context and adds it to the call stack. Here sayMyName is invoked, so javascript creates an execution context of sayMyName and add it to the call stack, the sayMyName function calls findName function and an execution context is being created for findName function which is added to call stack finally printName is called so its execution context is also added to the stack. When printName function execution is finished by returning the name it is popped off from the stack and then findName is popped off and then sayMyName is popped off.
Below is the Empty call stack when all the execution context are popped off the stack
The above scenario is almost right but one thing is missing is the global execution context
Whenever javascript engine runs over code, It creates a global execution context under which our code gets executed. The global execution context is popped off from the stack when our last line of the code gets executed. For the global execution context, we can say that it is the first thing that is pushed to call stack by javascript engine and is the last execution context to be popped off from the stack.
The most important line I want to say is that: whenever any code is executed it is executed inside an execution context.
Let's summarize what we have learned whenever over code is run inside the javascript engine it provides a global execution context inside which over code is run and when we run a function a new execution context is created.
Lexical Environment
Lexical Environment means where you write your code not how it get executed. Let’s see an example
Each Execution context has its own lexical environment.
In the Global execution context, our lexical environment contains findName and sayMyName function.
findName execution context has its own lexical environment which contains printName function
printName execution context has its own lexical environment which contains logMyName function.
let me repeat myself that lexical environment defines where your code is written and each execution context has its own lexical environment.
Variable Environment
Which variables reside inside the execution context is defined by the variable environment. All variable defined in your code has memory allocation in-memory heap but which variables are attached to execution context is defined by variable environment, Let’s see an example
In this example, we have isValid variable in three different variable environment
On line 12 we have variable isValid with value false in global variable environment. On line 7 we have variable isValid with the value true in ‘one’ function variable environment.On Line 2 we have variable isValid with the value undefined in ‘two’ function variable environment.
By seeing the value of console.log in the output you can understand how important is to understand the variable environment.
So by now, we have understood what is execution context, lexical environment, variable environment. These are the core concept after clearing these terms we can easily understand scopes. Lets now discuss scopes.
Scope in Javascript
In javascript, our lexical scope ( available data + variable depends on where the function was defined) determines our available variables. Not where the function is called (dynamic scope)
Let's see an example to better understand it
In the above example, we will try to understand the scope and scope chain
As we know that each function has its own execution context and variable environment, Let's distinguish this in the example
sayMyName: It variable environment has ‘a’ variable
findName: It variable environment has ‘b’ variable
printName: It variable environment has ‘c’ variable
In javascript whenever we want to access variable first it sees in its own variable environment if it's not there then it looks iteratively in the parent’s variable enviroment until it finds the desired variable
For example, if we want to access variable ‘a’ inside printName function, how execution will flow let see:
Firstly javascript engine will look into printName variable environment in which its not there, then it will look into the printName parent variable enviroment that is findName variable environment, in which it is not defined, then it will look into findName parent variable environment that is sayMyName variable environment which has ‘a’ variable defined in its variable environment, from here the value is resolved. This scope chain lookup goes upto global variable environment.
Now we have understood the scope and scope chain, lets discuss one more important topic.
Function scope vs block scope
Remember scope means what variable we have access to and javascript has function scope, every time we create a function we create an execution context that has its own variable environment, from es6, javascript included block scope. Block scope is created when it sees curly braces ({}) for example if block, for block creates a block scope. Let see an example of this.
Here we have created two function loop and loopBlockScope, The loop function uses var in for loop and we are accessing its value outside the for loop as ‘var’ respect function scope and we are inside the function so its value will be printed. In loopBlockScope, we are having the same logic as in loop function except we are using let which respect block scope, so accessing a variable outside the block scope as we are doing on line 14 will generate an error.
The key thing to remember is that var respect function scope while let and const respect block scope
I hope by know you have understood scope in javascript.