An Overview of the Engine, the Runtime, and the Call Stack by Alexander Zlatkov

This first chapter on how JavaScript works, 18 chapters in total, will continue to be updated, and you can also keep an eye on it in case you get lost


As JavaScript becomes more popular, teams are using it in many different technology stacks — front ends, back ends, hybrid APPs, embedded devices, and so on.

This article is the first in a series to delve deeper into Javascript and how it works: We think you can write better code and applications by understanding the components of Javascript and how they all work together. We’ll also share some rules of thumb for building SessionStack (the author’s company), a lightweight JavaScript application that must be powerful and high-performance to remain competitive.

As GitHut Stats shows, JavaScript ranks first in terms of the total number of pushes in the active repository and GitHub. It’s not far behind in other categories.

If projects rely more and more on JavaScript, that means developers have to take advantage of everything the language and ecosystem have to offer, and learn more and more about what’s inside, to build great software.

But it turns out that there are a lot of developers who use JavaScript every day without understanding its internals.

An overview of the

Almost everyone has heard of the V8 engine, and most people know that JavaScript is single-threaded or that it is using callback queues.

In this article, we’ll go through all of these concepts in detail and explain how JavaScript actually works. With this detailed knowledge, you can write better, non-blocking applications that take advantage of the apis provided.

If you’re new to JavaScript, this blog post will help you understand why JavaScript is so “weird” compared to other languages.

If you’re an experienced JavaScript developer, hopefully this will give you new insights into how the JavaScript runtime you use every day actually works.

JavaScript engine

One popular JavaScript engine is Google’s V8, which is used in Chrome and Node.js. For example, here is a simple view of V8:

  • Memory Heap – Where Memory is allocated
  • Call stack – This is where the stack frame is when the code executes

Run time

There are many apis in browsers that almost all JavaScript developers use (for example, “setTimeout”). None of these apis are provided by the JavaScript engine.

So where did they come from?

The reality, it turns out, is a little more complicated.

And, of course, there are the very popular Event loops and callback queues.

Call stack

Javascript is a single-threaded programming language, which means it has only one call stack. Because we can only do one thing at a time.

The call stack is a data structure that keeps track of where we are in the program. Whenever we enter a function, we put it on the stack from the top, and if we return from a function, we remove it from the top of the stack. That’s what the call stack does.

As an example, look at the following code

function multiply(x, y) {
    return x * y;
}
function printSquare(x) {
    var s = multiply(x, x);
    console.log(s);
}
printSquare(5);
Copy the code

The call stack is empty when the engine starts executing this code. After that, each step is shown below:

Stack Frame

We can also see exactly how stack paths are constructed when an exception is thrown – basically the state of the stack at the time of the exception, as shown in the following code:

function foo() {
    throw new Error('SessionStack will help you resolve crashes :)');
}
function bar() {
    foo();
}
function start() {
    bar();
}
start();
Copy the code

How this code executes in Chrome (assuming it’s in a foo.js file) yields the following stack path:

function foo() {
    foo();
}
foo();
Copy the code

When the engine starts executing this code, it initially calls the function “foo”. But this function is recursive, and it starts calling itself without termination conditions. So each step is the function adding itself to the stack over and over again. It looks like this:

The single-threaded mode also has some limitations. Javascript has only one call stack. What happens when the current code on the call stack takes a long time to execute?

Concurrency & Event Loop

What happens when your function consumes a lot of time in the call stack to process a task? Imagine that you need to convert some complex image in your browser using JavaScript.

You might ask, why is this a problem? The crux of the problem is that while the call stack is executing, the browser cannot perform its task – it is blocked. This also means that the browser can’t render, can’t run other task code, and it’s just stuck there. This can be a problem if you want a flow web application.

That’s not the only problem. Once the browser starts processing the many tasks in the “call stack,” it can stop responding for quite some time. And most browsers adopt a scheme that throws an error asking you if you want to terminate the page.

So how do we execute time-consuming code without clogging the UI and causing the browser to become unresponsive? The solution is asynchronous callback.

This will be covered in the second chapter of our “How JavaScript Works” series, “Take a closer look at the V8 Engine & 5 Tips for Writing Optimal Code.”

Other articles in this series

  1. An overview of the engine, runtime, and call stack
  2. Learn more about the V8 engine & 5 tips on How to Write Optimal code
  3. Memory Management & How to deal with 4 common Memory leaks
  4. Event loops and the rise of asynchronous programming & 5 ways to Code better with Async /await
  5. Learn more about WebSockets and HTTP2 with SSE & How to choose the right path
  6. Compare WebAssembly & Why is it better than JavaScript in some cases
  7. The construction of Web Workers & 5 cases where you need to use it
  8. Service Workers, its lifecycle and use cases
  9. Web Push Notifications mechanism
  10. Track DOM changes through MutatioinObserver
  11. Rendering engine and optimization tips
  12. In-depth understanding of the network layer & performance optimization and security
  13. Understand the inner workings of CSS and JS animation & performance optimization
  14. Parsing, Abstract Syntax tree (ASTs) & How to optimize parsing time
  15. Internals of Classes and Inheritance & Babel and TypeScript Escape
  16. Storage Engine & How to choose the right Storage API
  17. The inner workings of Shadow Dom & How to build independent components
  18. WebRTC and peer-to-peer mechanisms