To oversee the execution contexts, the JavaScript engine utilizes a call stack. Although the operation of the JavaScript call stack occurs internally, we will explore its functionality in this discussion.
In this segment, we will explore the JavaScript call stack and its functionality. Additionally, we will examine an example that will enhance our comprehension of this concept.
What is JS Call Stack
JavaScript execution contexts, which include the Global execution context and the function execution context, are processed by the JavaScript engine. To effectively manage these execution contexts, the JavaScript engine utilizes a call stack. The JS call stack serves as a data structure that monitors the functions that are being called and executed. Consequently, when a user initiates a function for execution, that specific function is added to the call stack. Conversely, when the user completes a function, it indicates that the function is removed from the call stack. Therefore, the call stack operates as a standard stack data structure that adheres to the principle of stack order, specifically LIFO (Last In First Out).
Role of JavaScript Call Stack
There are the following points where the call stack is being used by the JS engine:
- When any script is executed by the user, the JS engine creates a Global execution context and then adds it on the call stack and at the top of the stack so that it may get executed.
- When any function is invoked, the JS engine creates a Function execution context and adds it on the stack and at the top of the stack so that the invoked function may get executed.
- In case a function invokes another function, the JS engine creates a Function execution context for the invoked function, adds it to the top of the stack, and begins the execution.
- When any function execution gets completed, the JS engine pops it out of the stack and continues the execution of the other functions stored in the stack.
- If no space is left in the stack and we try to push more functions, it throws a "stack overflow" error, and if no further execution context is present in the call stack, it throws a "Stack Underflow" error.
JavaScript Call Stack Example
Let’s examine a practical example to grasp the application of the JavaScript Call Stack function:
function getSum(x, y) {
return x+ y;
}
function findavg(x,y) {
return getSum(x,y) / 2;
}
let z = findavg(10, 20);
How the code works
In the above code, we have created two functions, getSum and findavg , and the execution of the script begins in the following described steps:
- When the execution of the script begins, the JS engine initially creates a global execution context (i.e., global function) and adds it to the top of the call stack.
- The global execution moves to the execution phase of the life cycle after entering the creation phase, as you can see in the below image:
- The findavg (10, 20) function gets invoked, and so the JS engine creates the function execution context for it. Then push it on the top of the call stack.
- So, now in the call stack, two functions are pushed, i.e., global and findavg, and on the top of the stack, the findavg function is present, as you can see in the below image:
- The JS engine begins the execution of the findavg function because it exists on the top of the stack, as you can see in the image:
- As in the code, the getSum function is invoked inside the findavg function definition, so the JS engine creates a function execution context for the getSum function and pushes it on the top of the stack.
- Now, in the stack, there are three functions present, which are global , findavg , and getSum functions, as you can see in the below image: There are two functional execution contexts and a global execution context as you can see below:
- So, the JS engine executes the getSum function first and pops it out of the call stack.
- Similarly, the findavg function gets executed and gets out of the call stack.
- As both executions of the functions are completed, and no other function for execution is left in the call stack. The JS engine stops the execution of the call stack and moves for the other execution tasks.
When does call stack overflow
The overflow situation arises when the call stack runs out of available space, or it can also happen due to a recursive function that lacks a termination condition. The size of the JavaScript call stack is predetermined and varies based on the specifics of the host environment, which can either be Node.js or a web browser. Consequently, when the stack reaches its defined capacity, a stack overflow error is triggered.
Example:
The following example illustrates the condition of a stack overflow:
function test(){
test();
}
test();
In the code presented above, we observe that the test function is being called recursively. This implies that the function will continue to run until it surpasses the maximum call stack size permitted by the hosting environment, ultimately leading to a stack overflow error.
Point to be noted:
JavaScript operates as a synchronous and single-threaded programming language. This indicates that when a script is run, the JavaScript engine processes the code sequentially, following a top-to-bottom approach. Consequently, the JavaScript engine maintains a single call stack and can handle only one operation at a given moment.