- JavaScript Call Stack
- Introduction to JavaScript Call Stack
- JavaScript call stack example
- Stack overflow
- Asynchronous JavaScript
- Summary
- Call stack
- Example
- See also
- Found a content problem with this page?
- The JavaScript Call Stack — What It Is and Why It’s Necessary
- How does the call stack handle function calls?
- What causes a stack overflow?
- In summary
JavaScript Call Stack
Summary: in this tutorial, you will learn about the JavaScript Call Stack which is a mechanism to keep track of the function calls.
Introduction to JavaScript Call Stack
A call stack is a way for the JavaScript engine to keep track of its place in code that calls multiple functions. It has the information on what function is currently being run and what functions are invoked from within that function…
Also, the JavaScript engine uses a call stack to manage execution contexts:
The call stack works based on the LIFO principle i.e., last-in-first-out.
When you execute a script, the JavaScript engine creates a global execution context and pushes it on top of the call stack.
Whenever a function is called, the JavaScript engine creates a function execution context for the function, pushes it on top of the call stack, and starts executing the function.
If a function calls another function, the JavaScript engine creates a new function execution context for the function being called and pushes it on top of the call stack.
When the current function completes, the JavaScript engine pops it off the call stack and resumes the execution where it left off.
The script will stop when the call stack is empty.
JavaScript call stack example
Let’s start with the following example:
function add(a, b) < return a + b; > function average(a, b) < return add(a, b) / 2; > let x = average(10, 20);
Code language: JavaScript (javascript)
When the JavaScript engine executes this script, it places the global execution context (denoted by main() or global() function on the call stack.
The global execution context enters the creation phase and moves to the execution phase.
The JavaScript engine executes the call to the average(10, 20) function and creates a function execution context for the average() function and pushes it on top of the call stack:
The JavaScript engine starts executing the average() since because the average() function is on the top of the call stack.
The average() function calls add() function. At this point, the JavaScript engine creates another function execution context for the add() function and places it on the top of the call stack:
JavaScript engine executes the add() function and pops it off the call stack:
At this point, the average() function is on the top of the call stack, the JavaScript engine executes and pops it off the call stack.
Now, the call stack is empty so the script stops executing:
The following picture illustrates the overall status of the Call Stack in all steps:
Stack overflow
The call stack has a fixed size, depending on the implementation of the host environment, either the web browser or Node.js.
If the number of execution contexts exceeds the size of the stack, a stack overflow error will occur.
For example, when you execute a recursive function that has no exit condition, the JavaScript engine will issue a stack overflow error:
function fn( ) < fn(); >fn(); // stack overflow
Code language: JavaScript (javascript)
Asynchronous JavaScript
JavaScript is a single-threaded programming language. This means that the JavaScript engine has only one call stack. Therefore, it only can do one thing at a time.
When executing a script, the JavaScript engine executes code from top to bottom, line by line. In other words, it is synchronous.
Asynchronous means the JavaScript engine can execute other tasks while waiting for another task to be completed. For example, the JavaScript engine can:
- Request for data from a remote server.
- Display a spinner
- When the data is available, display it on the webpage.
To do this, the JavaScript engine uses an event loop, which will be covered in the following tutorial.
Summary
- JavaScript engine uses a call stack to manage execution contexts.
- The call stack uses the stack data structure that works based on the LIFO (last-in-first-out) principle.
Call stack
A call stack is a mechanism for an interpreter (like the JavaScript interpreter in a web browser) to keep track of its place in a script that calls multiple functions — what function is currently being run and what functions are called from within that function, etc.
- When a script calls a function, the interpreter adds it to the call stack and then starts carrying out the function.
- Any functions that are called by that function are added to the call stack further up, and run where their calls are reached.
- When the current function is finished, the interpreter takes it off the stack and resumes execution where it left off in the last code listing.
- If the stack takes up more space than it was assigned, a «stack overflow» error is thrown.
Example
function greeting() // [1] Some code here sayHi(); // [2] Some code here > function sayHi() return "Hi!"; > // Invoke the `greeting` function greeting(); // [3] Some code here
The code above would be executed like this:
- Ignore all functions, until it reaches the greeting() function invocation.
- Add the greeting() function to the call stack list.
In summary, then, we start with an empty Call Stack. Whenever we invoke a function, it is automatically added to the Call Stack. Once the function has executed all of its code, it is automatically removed from the Call Stack. Ultimately, the Stack is empty again.
See also
Found a content problem with this page?
This page was last modified on Jun 8, 2023 by MDN contributors.
Your blueprint for a better internet.
The JavaScript Call Stack — What It Is and Why It’s Necessary
Charles Freeborn
The JavaScript engine (which is found in a hosting environment like the browser), is a single-threaded interpreter comprising of a heap and a single call stack. The browser provides web APIs like the DOM, AJAX, and Timers.
This article is aimed at explaining what the call stack is and why it is needed. An understanding of the call stack will give clarity to how “function hierarchy and execution order” works in the JavaScript engine.
The call stack is primarily used for function invocation (call). Since the call stack is single, function(s) execution, is done, one at a time, from top to bottom. It means the call stack is synchronous.
The understanding of the call stack is vital to Asynchronous programming (which we will look at in a later article).
In Asynchronous JavaScript, we have a callback function, an event loop, and a task queue. The callback function is acted upon by the call stack during execution after the call back function has been pushed to the stack by the event loop.
But before we jump the gun, let us first attempt to answer the question — What is the call stack?
At the most basic level, a call stack is a data structure that uses the Last In, First Out (LIFO) principle to temporarily store and manage function invocation (call).
Let’s break down our definition:
LIFO: When we say that the call stack, operates by the data structure principle of Last In, First Out, it means that the last function that gets pushed into the stack is the first to be pop out, when the function returns.
Let us take a look at a code sample to demonstrate LIFO by printing a stack trace error to the console.
function firstFunction() < throw new Error('Stack Trace Error'); >function secondFunction() < firstFunction(); >function thirdFunction() < secondFunction(); >thirdFunction();
When the code is run, we get an error. A stack is printed showing how the functions are stack on top each other. Take a look at the diagram.
You will notice that the arrangement of the functions as a stack begins with the firstFunction() (which is the last function that got into the stack, and is popped out to throw the error), followed by the secondFunction() , and then the thirdFunction() (which is the first function that gets pushed into the stack when the code is executed).
Temporarily store: When a function is invoked (called), the function, its parameters, and variables are pushed into the call stack to form a stack frame. This stack frame is a memory location in the stack. The memory is cleared when the function returns as it is pop out of the stack.
Manage function invocation (call): The call stack maintains a record of the position of each stack frame. It knows the next function to be executed (and will remove it after execution). This is what makes code execution in JavaScript synchronous.
Think of yourself standing on a queue, in a grocery store cash point. You can only be attended to after the person in front of you have been attended to. That’s synchronous.
This is what we mean by “manage function invocation”.
How does the call stack handle function calls?
We will answer this question by looking at a sample code of a function that calls another function. Here is the example code:
function firstFunction() < console.log("Hello from firstFunction"); >function secondFunction() < firstFunction(); console.log("The end from secondFunction"); >secondFunction();
This is what happens when the code is run:
1. When secondFunction() gets executed, an empty stack frame is created. It is the main (anonymous) entry point of the program.
2. secondFunction() then calls firstFunction() which is pushed into the stack.
3. firstFunction() returns and prints “Hello from firstFunction” to the console.
4. firstFunction() is pop off the stack.
5. The execution order then move to secondFunction() .
6. secondFunction() returns and print “The end from secondFunction” to the console.
7. secondFunction() is pop off the stack, clearing the memory.
What causes a stack overflow?
A stack overflow occurs when there is a recursive function (a function that calls itself) without an exit point. The browser (hosting environment) has a maximum stack call that it can accomodate before throwing a stack error.
function callMyself() < callMyself(); >callMyself();
The callMyself() will run until the browser throws a “Maximum call size exceeded”. And that is a stack overflow.
In summary
The key takeaways from the call stack are:
1. It is single-threaded. Meaning it can only do one thing at a time.
2. Code execution is synchronous.
3. A function invocation creates a stack frame that occupies a temporary memory.
4. It works as a LIFO — Last In, First Out data structure.
We have used the call stack article to lay the foundation for a series we will be looking at on Asynchronous JavaScript (which we will be looking at in another article).
All code samples can be found in this GitHub repo.
Thank you for reading. If this article was helpful please give it some claps ? so others can find it. I will like to read your comments also.