Javascript Runtime

Call Stack

JavaScript engine uses a call stack to manage  execution contexts : the Global Execution Context and Function 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 that is 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 in the last code listing.

The script will stop when the call stack is empty.

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 the execution contexts exceeds the size of the stack, a stack overflow will occur.


Asynchronous Calls

JavaScript is the single-threaded programming language. The JavaScript engine has only one call stack so that 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 is the opposite of synchronous, which means happening at the same time. So how does JavaScript carry asynchronous tasks such as callbacks,  promises , and  async/await ? This is where the event loop comes into the picture.

If you have a function that takes a long time to execute, then you cannot do anything on the web browser during the function’s execution. The webpage just hangs. A function that takes a long time to execute is known as a blocking function. Technically, the blocking functions block all the interactions with the webpage such as mouse click. Some examples of blocking functions are the functions that download files from a remote server or functions that call an API from an external server.

To prevent blocking functions from blocking other activities, you typically wrap them in callback functions which can be executed later.

When an asynchronous function is invoked, the function is then placed into a queue called callback queue or task queue.

The event loop is a constantly running process that monitors both the callback queue and the call stack.

If the call stack is not empty, the event loop waits until it is empty and places the next function from the callback queue to the call stack. If the callback queue is empty, nothing will happen.

In this example, the timeout is 0 second so the message 'Execute immediately.' should appear before the message 'start!'. However, it is not the case. The console.log('Execute immediately.');is placed on the callback queue and executed only when the call stack is empty. In other words, it is executed only after the console.log('end!') is completed.


setTimeout(() => {
    console.log('Execute immediately.');
}, 0);



Execute immediately.



Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!


Leave a Reply

Your email address will not be published. Required fields are marked *