Understanding Execution Context and Call Stack in JavaScript.
intro to javascript and blog
JavaScript is a synchronous and single-threaded language.
- Single-threaded : single-threaded language means JavaScript runs one statement at a time one after the other as opposed to multi-threaded languages where a program can be divided into chunks and these chunks gets executed parallelly at the same time.
- Synchronous : synchronous means the statements in JavaScript are executed in an order where the next statement is executed only when the current statement has been completely executed.
Execution Context
Execution context is an abstract concept that can be treated as a container that contains code that is currently being executed and everything else that is helping to run that code. All JavaScript code runs inside an execution context.
There are two types of execution contexts:
Global Execution Context : It is the default execution context that gets created when a program is run. Any code that is not inside a function gets executed inside the global execution context. There can only be one global execution context in a program.
Functional Execution Context: Whenever a function is invoked, a new execution context gets created. This execution context is called the functional execution context. Every function runs inside its own execution context. When a function's execution is completed, its execution context gets deleted. As a functional execution context gets created whenever a function is invoked or called, there can be
n
number of functional execution contexts.
Execution context is made of two components:
- Memory: All the variables and functions in a program get stored inside the memory component during the memory creation phase of the execution context.
- Code: JavaScript code is executed one line at a time from top to bottom inside the code component during the code execution phase.
The execution context is created in two phases:
Memory creation phase: In this phase the code present in the execution context is allocated memory as a key- value pair to variables and functions.
- When memory is allocated to a variable, the variable gets initialized with a special value undefined by default.
- Whereas, when allocating memory to a function, the whole code of that function gets placed in the memory.
var animal = "Dog";
var sound = "bow, bow"
function animalSound(animal, sound){
console.log("A ", animal, " says, ", sound)
}
animalSound(animal, sound);
memory creation phase image goes here
Code execution phase: In this phase the code is executed line by line from top to bottom.
Let's use above code snippet to understand code execution phase.
When statement
var animal = "Dog";
gets executed; the variableanimal
in the memory get's assigned the value"Dog"
replacing the valueundefined
with which it was initialized in the memory allocation phase . Similarly, the variablesound
in the memory get's assigned the value"bow, bow"
.Next, the control reaches
line 3
where there is nothing to execute as the function is being declared and this function was already allocated memory in the memory creation phase. Hence, the control moves to line 4.On
line 4
, theanimalSound
function is invoked and hence another execution context is created.
functional execution context image goes here
The execution context does the following:
- Allocates memory to the parameters
animal
andsound
and initializes them toundefined
in the memory allocation phase. - In the code execution phase, the parameters
animal
andsound
get allocated the values "Dog" and "bow, bow..." respectively using the values that are received from the arguments passed during the function invocation. - The string gets logged in the console using
console.log
web api.
Since, whenever a function is invoked a execution context is created; a function can also be invoked inside another function, that will cause one more execution context to be created inside the existing execution context that was created when the original function was invoked. This can go on n
number of times. The task of managing all these execution contexts is done by the Call Stack
nested functional execution context image goes here
Call Stack
Call stack does the job of managing the execution contexts. When a program is run, a global execution context is created and pushed into the call stack. The code statements inside the global execution context get executed one by one until a function invocation is encountered. As soon as a function is invoked a new execution context is created and pushed into the call stack. Now this newly pushed execution context is on the top of the call stack and the code inside it gets executed. Upon finishing execution, the control gets back to the execution context where the function was invoked. This way call stack manages execution contexts and makes sure the code is run in orderly manner.