JavaScript Engine And Runtime

JavaScript Engine And Runtime

Understanding what happens behind the scenes in javascript execution

ยท

5 min read

For you to become a competent JavaScript developer, you should have a basic understanding of how code is compiled and executed. In this article, we will explore how JavaScript works behind the scenes to compile our code.

Prerequisite

  • Basic Knowledge of JavaScript

JavaScript Engine

Generally, JavaScript Engines are programs that execute JavaScript code and convert it into a language computer programs can understand.

Every browser has its engine, the most common being google's V8 engine - which powers google chrome and also Node.js.

Note: Other browsers have their engine. see here.

Components of the JavaScript Engine

JavaScript Engines are composed of two (2) components, namely;

  • Call Stack
  • Heap

Call Stack

This is where our code is executed using the execution context - which is where the code that is currently running is located, along with everything that aids its execution.

The Heap

This is an unstructured memory pool that stores all the objects that our application needs.

jsengine.png Diagram of the Javascript Engine.

How Is JavaScript Code Compiled to Machine code?

Before we go into how our code is compiled to machine code, let's note that a computer's processor can only understand 0s and 1s. Every single computer program needs to be converted into machine code and this can be done using compilation or interpretation.

Now let's examine the differences between compilation and interpretation to get a better grasp of each.

Compilation: A compilation is a process by which all of the code is converted into machine code at one time and written to a binary file, which is a file that stores information in bytes and can be interpreted by a computer as something other than textual characters.

Flowchart.jpg Flowchart representing the steps in compilation

Interpretation: In this case, the interpreter runs through the source code, then executes it line by line. It involves just one step and doesn't require any portable file.

Flowchart (1).jpg Flowchart representing the steps in interpretation

Having learned about interpretation and compilation, which technique does JavaScript use when executing the code? It uses Just-In-Time (JIT) Compilation.

Just-In-Time (JIT) Compilation:

While interpreted languages are usually much slower than compiled languages, this is not the case with JavaScript since it uses a Just-In-Time(JIT) compilation method for its execution, which is a combination of interpretation and compilation.

In JIT, the entire code is converted into machine code at once then it is executed immediately.

Flowchart (2).jpg Flowchart representing the steps in Just-In-Time Compilation

Steps in Just-In-Time compilation

The following are steps used to carry out the JIT compilation;

As the JavaScript code enters the engine;

Step 1: The code gets parsed - parsing means reading the code. The code is parsed into a data structure called the abstract syntax tree (AST). The AST first splits up every line of code into pieces that are meaningful to the language (like the const / function keyword) and saves all the pieces into the tree in a structured way. The AST also checks if there are syntax errors and the resulting tree is used to generate the machine code.

Note:

  • You don't need to know what an AST looks like.
  • Does the AST have anything to do with the DOM tree? ๐Ÿšซ No, the AST is just a representation of our entire code in the engine.

Step 2: The code gets compiled - The AST that is generated is compiled to machine code.

Step 3: Execution happens - Execution happens in the engines' call stack. JavaScript first creates an unoptimized version of machine code in the beginning, so it can start executing as fast as possible. In the background, the code is recompiled and optimized then the previous unoptimized version will be swapped with the most optimized version.

Note: All this happens in special threads that we can't access from our code.

JavaScript Runtime.

The Javascript runtime refers to the location where your javascript code is executed when you run it. Essentially it can be seen as a big box that contains all the necessary components for using JavaScript, in this case in the browser.

The heart of the JavaScript runtime is the JavaScript Engine.

Components of the JavaScript Runtime

Without the JavaScript engine, there is no Runtime, but the engine alone is not enough. In order for the runtime to work properly, it must contain other components, which are;

  • JavaScript Engine
  • Web APIs
  • Callback queue

Web APIs

Web APIs are application programming interfaces for the Internet. Web APIs increase a browser's functionality. They are functionalities provided to the engine but are not part of the JavaScript language. JavaScript gets access to the Web APIs through the global window object.

Callback Queue

This is a data structure that contains all the callback functions that are ready to be executed. Callback queues, as their name suggests, are queues, so functions added to them are handled in a first-in-first-out order.

jsRuntime.png Diagram of the Javascript Runtime

let's take a practical example:

const burger = document.querySelector(".burger");
const navLinks = document.querySelector('.nav-links')

burger.addEventListener("click", () => {
  navLinks.classList.add('hidden')
});

Here, we have a click event listener (which is also a callback function) attached to the burger element. The following are steps in which this code gets executed when the burger is clicked behind the scene;

Step 1: Callback function is put into the callback queue.

Step 2: When the call stack is empty, the callback function is passed into the call stack, so it can be executed. This is handled by the event loop.

The event loop

JavaScript's asynchronous programming relies on the event loop. The event loop checks if the call stack is empty, and if it is, takes the callback function and puts it into the call stack to be executed.

Note:

  • The event loop is essential for JavaScript non-blocking concurrency model.

  • Since JavaScript can be used outside the browser e.g. Node.js, the runtime environment varies. The runtime for Node.js consists of the engine, callback queue, multiple c++ bindings, and thread pool.

Conclusion

As a reader, if you don't understand how JavaScript works behind the scenes, I hope this article has been able to shed some light on the subject. Although it isn't a deep article, the knowledge alone is sufficient to help you understand how JavaScript works.

ย