Scope
Scope in javascript is directly related to the lexical environment, if we first understand the lexical environment it will be very easy for us to understand scope and scope chain, and it will also help us to understand closures also.
Scope
Where you can access the specific variable or function in our code
let's see some examples
1 function getValue(){
2 console.log(b)
3 };
4 var b = 10;
5 getValue(); // output : 10
1 function getValue(){
2 var b = 10;
3 };
4 console.log(b) // error b is not defined
5 getValue();
simply we get the value, but if I declare the variable b
inside the function and try to access the variable outside the function, javascript simply throws a reference error `b is not defined, So here's Scope come into a place
There are two aspects of the scope in the case of var b
- what is the scope of a variable or
- Is variable lies inside the scope of a function
Before going further let's see what is lexical environment
Lexical environment
The lexical environment is the local memory along with the lexical environment of its parent Lexical in general means in a hierarchy or in a sequence. Whenever a new execution context(EC) is created a new lexical environment is created and it is referenced in the local EC in memory space. let's see an example
1 function a(){
2 var b =1
3 c()
4 function c(){
5 }
6 }
7 a()
From the definition, we can say the function c
is lexically inside the function a
and function a
is lexically inside the global scope this is known as lexical, so when I say the lexical environment of functions c
is the local memory of function along with the lexical environment of its parent, in this case, the parent is function a
and for function a
the lexical environment is the local memory of function a
( local memory means the local execution context memory of a function a
) and the lexical environment of its parent ( parent of function a
is a global execution context
let's see some example
function a(){
function b(){
var one = 2
console.log(one) // 2
}
console.log(one)
}
var one = 3
a()
console.log(one) // 3
Therefore, we can say that javascript will first search in the local memory for a variable inside function b, and if the variable is present, javascript will use it rather than search in the lexical environment of function a
In the case of function b
the variable is not present inside the local memory of function a
so it will try to find it in the lexical environment of its parent
Types of Scope
JavaScript has three different types of scope.
- Global Scope
- Function Scope
- Block scope Let's take a few examples to understand these three different scopes.
Global scope
Variables declared outside of functions or code blocks (curly braces { }) are considered to have a global scope. The outermost scope contains the entire code, and there is only one global scope in the program.
The variables defined in the global scope are named Global Variables and can be accessed and altered in any other scope.
Function Scope / Local Scope
Each and every function creates its own scope. And the variables declared inside that function are only accessible inside that function and any of its nested functions. This is also called Local Scope.
Block Scope
ES6 introduced let and const variables. With that, it introduced the block scope. Block scope means that the variables defined inside a code clock {} can only be used inside it.
for example, if a variable declares using const
or let
inside if else
condition or in a for loop
the variable can only be accessible inside the block or inside the {} we can not access them outside the {} or outside the block of if-else or loop or any other block.
const one = 1
if (one === 1){
var two = 2
const three = 2
}
console.log(two) // 2
console.log(three) // ReferenceError: three is not defined
In the case of var
, we can access them because the var
is stored inside the global memory and we can access variables inside the global memory anywhere inside the code
Scope chain
function a(){
function b(){
console.log(one) // 2
}
console.log(one)
}
var one = 2
a()
The Scope chain is nothing but a chain of lexical environments and their parent references are called the scope chain in the above example we can see that function b
first finds the variable in the local scope then it tries to find it in the parent scope and finally in the global scope
javascript is Single-threaded language
Javascript is a single-threaded synchronous scripting language, javascript has one call stack whenever javascript code run global execution context is pushed inside the call stack and javascript code will execute line by line or we can also say that in a single thread synchronously(In other words, one command is processed at a time) in an execution context.
Let's see an example
function sum(a , b){
alert("In a function")
return a + b;
}
const a = 1;
const b = 2;
console.log("Before invoking the function")
const result = sum(a,b)
console.log(result)
as you can see above, The execution is stopped for alert
so here we can say that javascript is single threaded language
Execution context
Imagine your code is placed inside a box whenever you write JS code. That box is the Execution context, a conceptual environment created by JS for code evaluation and execution.
Execution context has two components, the memory component, and the code component memory component is also called a variable environment in which all the variables and functions are stored in `key: value pairs
And the code component is also called a thread component in which the whole code is executed line by line. all though javascript is a synchronous
single-threaded
language
its means it executes one command at a time,
The execution context is created in two-phase
Memory creation phase
Let's take a look at a simple js code example,
var a = 3;
function square(num){
var ans = num*num
return ans
}
var square0ne = square(a)
var squareTwo = square(5)
In the memory creation phase as soon as the js encounter the variable a
JS allocates the memory for variable a
and in the memory JS stores a value called undefined
when js encounter the function square
, the memory is allocated for a function and the entire function is stored as a value to their in a memory component to their identifier
for variable squareOne
and squareTwo
JS allocate the memory and stores the undefined
to their identifier
NOTE: For all the variable's in the memory creation phase the value is `undefined for the variable identifier
As soon as javascript allocate memory to all variable and function it will go into the next phase called the code execution phase
Code execution phase
Finally in the code execution phase when javascript encounters the variable the actual >value of a variable is stored in a memory to their identifier
In the above example when the js encounter the variable a
the actual value of a
which is 3
is stored in the memory to their identifier a
now here is the interesting part of the above code example, when js invokes or calls the function one more local execution context is created inside the code component. local execution context is also created in two-phase memory creation and code execution phase
Let's see how it's looks
In the above image, we can see that the local execution is created for a function square
since the function is invoked for their pointer is on
1 var a = 3;
2 function square(num){
3 var ans = num*num
4 return ans
5 }
6 var squareOne = square(a) // << pointer
7 var squareTwo = square(5)
In the memory creation phase, the memory is allocated for the sum
variable and for property num
which is passed as an argument a
whose value is equal to 3.
After the memory creation phase, the code execution phase takes place
1 var a = 3;
2 function square(num){ // << pointer
3 var ans = num*num
4 return ans
5 }
6 var squareOne = square(a)
7 var squareTwo = square(5)
as you can see that the pointer goes on line 2 now JS, in memory the value of num set to 3 after that the pointer goes on line 3, after the calculation the value of ans
is set as 9
after that, the pointer goes on line 4 which returns ans
to the global execution context, and the value of ans
is set to the squareOne
hence the local execution context is removed from the code component of the global execution context
1 var a = 3;
2 function square(num){
3 var ans = num*num
4 return ans
5 }
6 var squareOne = square(a)
7 var squareTwo = square(5) // << pointer
now one more time local execution context is created for function square
, After executing the function it will return ans
, and the ans
will be set as a value for squareTwo
in the global execution context
hence all the code is now executed the whole global execution is deleted
Now let's take a look at the call stack for the same javascript code example
The Call Stack
A stack is a data structure that follows the Last in First Out (LIFO) principle. However, the Call Stack is a stack that keeps track of all the execution context created during code execution.
- The global execution context is initially added(pushed) on the execution stack by default, in the form of the global() object.
- A Function execution context or local execution context is added to the stack when a function is invoked or called.
- The Invoked function is executed and removed (popped) from the stack, along with its execution context.
function greeting() {
sayHi();
}
function sayHi() {
return "Hi!";
}
// Invoke the `greeting` function
greeting();
STEP 1: The GEC is created and pushed on the execution stack as the global() object. STEP 2: The greeting() function is invoked and pushed on the stack. STEP 2: The sayHi() function is invoked and pushed on the stack. STEP 3: The sayHi() function is popped off the stack. STEP 3: The greetings() function is popped off the stack.
hoisting in javascript
You may have encountered this in javascript when you console.log()
a var before declaring, instate of getting an error we get a strange value called undefined
let's see what's happened behind the seen.
What is hoisting
Hoisting is the process in javascript by which we can access the variables and functions even before we have initialized it without getting any error
let's take some example
1 var one = 2
2 function getValue(){
3 console.log("hello world")
4 }
5 console.log(one) // 2
6 getValue() // "hello world"
as you can see in the above javascript example nothing is new to us, we defined and initialize variable one
on line 1, and on line 2 we defined a function and call both of them after defining and ve got their respected value
but what happens when we tried to console.log()
the variable and invoke the function before defining them let's see
1 console.log(one);
2 getValue();
3
4 function getValue(){
5 console.log("hello world")
6 }
7 var one = 2;
here you can see in the above example var one
and function getValue()
got hoisted
but why the value of var one
is undefined and the function return hello world
before I explain this, let's see one more example
1 console.log(one);
2 console.log(getValue);
3
4 function getValue(){
5 console.log("hello world")
6 }
7 var one = 2;
so this is the same value for variable one
and function getValue
stored in a memory creation phase in the memory component of the global execution context, As we tried to access the value before defining javascript simply give the value stored in a memory,
But in the case of a function, the whole function is stored in a memory during the memory creation phase as you can see in the above image,
Function declarations and arrow functions are hoisted?
In the case of function declaration and arrow function, we can not invoke the function before the declaration because both types of declaring the function act like a variable and
during the memory creation phase, the value of this function is undefined
and if we tried to invoke this type of function we will get a type error,
Difference between undefined and not defined
From the above examples, we definitely can say how we got undefined for the var one but in case I tried to access some variable that is not declared or defined in an entire code so javascript throws a reference error: one is not defined Let's see
1 console.log(one);
2 console.log(getValue);
3
4 function getValue(){
5 console.log("hello world")
6 }
7 //var one = 2;
In the next article, we will try to understand how the javascript function works and take a look at the variable Environment,