JavaScript Execution Context & Call Stack
JavaScript Execution Context is the environment or scope in which the JavaScript code runs. In other words, it is the scope where all our objects, variables and functions are alive, defined and stored.
Functional Execution Context
Just before a function is being called, an execution context of type Functional Execution Context will be created and pushed to what is so called Execution Context Stack.
Global Execution Context
Every application has an entry.js file. This is the very first lines of script code (JavaScript code) that will run when the application starts. When the application starts, a Global Execution Context is created and pushed to the Execution Context Stack. This context is the first context that will be pushed to the stack and it is the global scope where all our functions and variables are found. The GEC has no access to its functions scopes.
The creation process of an execution context is briefly described below.
Context creation process
1. Create activation object which will contain all function arguments and variables
2. Create scope chain list which will contain all the variables that is found in the functions’ containing scope, including the “Higher-level” this.
3. this object initialization.
Call Stack
The Call stack in abstraction, is the execution order of our JavaScript functions (class constructors included also).
Whenever a context is created, it is pushed to the Call Stack and the function is executed.
When the function finishes execution, the context is poped out of the stack.
const B = function() {
return 'B';
}
const A = function() {
B();
return 'A';
}
If function A() has another function B() call, the function B context will be pushed to the Call Stack and B will execute, when B finished execution it is poped out of the Call Stack and return to function A execution.
const countdown = function(seconds = 0) {
if (typeof seconds !== 'number') {
return 'error';
}
if (seconds <= 0) {
return 'finish';
}
console.log(seconds + ' ');
countdown(seconds - 1);
};countdown(3);
If we take an example the countdown recursive function, we can say that our Call Stack changes are:
CallStack = [global];CallStack.push(countdown(3))
CallStack.push(countdown(2))
CallStack.push(countdown(1))
CallStack.push(countdown(0))CallStack.pop(countdown(0))
CallStack.pop(countdown(1))
CallStack.pop(countdown(2))
CallStack.pop(countdown(3))CallStack.pop(global)
// assume our global function ended