What is the JavaScript engine and how does it work

Recently, we launched a series aimed at teaching web developers how JavaScript works and what are the various components that make the process of compiling and executing code in JavaScript quick and easy.

The first post in this series was an overview of the JavaScript engine, call stack, and runtime environment. In this second part of this series of JavaScript tutorials, we will focus on the inner parts of the JavaScript engine and find out why JavaScript is no longer an interpreted programming language.

If you missed it or need a refresher, be sure to read part one of our series: How JavaScript Works Behind the Scenes.

What is the JavaScript engine?

The JavaScript engine is a program responsible for executing JavaScript code. All modern browsers come with their own version of the JavaScript engine, but the most popular is Google’s V8 engine. Google’s V8 engine powers Google Chrome browsers, as well as Node.js. Node.js is a JavaScript runtime used to build server-side applications outside of the browser.

Here is a list of the different JavaScript engines for each major internet browser:

  • V8 – Open-source JavaScript engine developed by Google for Chrome
  • SpiderMonkey – The JavaScript engine of Mozilla Firefox
  • JavaScriptCore – Open-source JavaScript engine developed by Apple for Safari
  • Rhinoceros – Open-source JavaScript engine maintained by the Mozilla Foundation for FireFox
  • chakra – A JavaScript engine for Microsoft Edge
  • JerryScript – A JavaScript engine for the Internet of Things (IoT).

Now that we understand what a JavaScript engine is, we can take a deeper look under the hood and learn more about the different components of JavaScript. So, with this look at the engine behind us, in the next section we will discuss how JavaScript code is compiled into machine code so that it can be executed.

Read: Top 10 AngularJS Alternatives

How does JavaScript compilation and interpretation work?

Let’s start by understanding the differences between a compiler and an interpreter. As web developers might know, a computer can only understand 0s and 1s (think of them as simple on/off switches). This is why every computer program must eventually be converted into machine code. This task is performed using a process called compilation or interpretation. We examine each of these processes in the next section.

What is compilation in programming?

During compilation, the entire source code is converted into machine code at once. Machine code is written in a portable file that can be run anywhere, regardless of platform or operating system. There are two steps involved in the code compilation process. In the first stage the machine code is built and in the second stage it is executed on the machine.

Execution of machine code occurs right after compilation. For example, any application that you currently use on your computer has been compiled first and you can now run it on your machine.

Read: Introduction to Garbage Collection in JavaScript

What is interpretation in programming?

On the other hand, while interpreting, the interpreter goes through the source code and executes it line by line. Unlike compilation, which involves a two-step process, in interpretation the code is read and executed at the same time. Of course, the source code still needs to be converted into machine language, but the code conversion does not happen in advance, but rather just before execution.

JavaScript interpretation example

What is just-in-time compilation?

JavaScript is a purely interpreted language. The problem with being an interpreted language, however, is that interpreted programming languages ​​are much slower in performance compared to compiled languages. This presents a problem for modern applications that require fast processing and high performance. Just imagine that you are playing an online game on your browser, and when you move a cube across a tile, it takes several seconds to reach the endpoint. Would such slowness be acceptable?

Many people still call JavaScript an interpreted programming language, but that is no longer the case. The current JavaScript engine uses both the concept of compilation and interpretation, known as Just in time (JIT) compilation.

In this approach, all of the source code is compiled into machine language at once and then executed. There are two more steps involved in the in advance compilation, but there is no portable file to run. This is a perfect solution for today’s fast performance demanding web applications because this process is much faster than just executing code line by line. This inclusion of JIT compilation is why JavaScript is technically no longer an interpreted programming language.

How does just-in-time (JIT) compilation work?

So how does the Just-in-Time JavaScript Compiler work? When a new piece of JavaScript code enters the JavaScript engine, the first step is to analyze the code. During this process, the code is parsed into a data structure called Abstract Syntax Tree (AST).

The abstract syntax tree first divides each line of code into meaningful chunks for JavaScript, such as the to leave, staticWhere a function key words. It then saves these pieces of code in a tree structure. The next step checks for syntax errors and, if none are found, the resulting tree is used to generate machine code.

Now let’s see a quick example of JIT in action. In the following JavaScript snippet, we’ve declared a variable on the left side, and on the right side is its AST equivalent:

JIT compilation explained JavaScript JIT Example

Here we have declared a constant variable with name val and gave it the value 45. As you can see from the AST tree side, besides the declaration there is a lot of extra code. Can you imagine all the superfluous code that would be generated in a large application?

In the next step, the generated AST is compiled into machine code. Then this machine language is executed. This is how modern JavaScript uses just-in-time compilation. Remember that the machine code execution process takes place in the JavaScript engine call stack.

JavaScript call stack

So far so good – at this point our code is running and this should be the end of the process. Not so fast – JavaScript has code optimization strategies to implement. At first, JavaScript creates very unoptimized machine code so that it can run scripts as quickly as possible. Then, in the background, this unoptimized code is recompiled and optimized, while the current code is executed. This is done most of the time and after each optimization cycle, the unoptimized code is swapped for the most optimized code, without ever stopping the execution. This is why the JavaScript engine works so fast.

The code optimization process takes place in special threads, separate from the main thread. JavaScript developers cannot access the code optimization algorithm from our source code. Although different engines implement the strategy in different ways, in a nutshell, this is how modern JavaScript Just-in-time compilation works.

Read: HTML, CSS and JavaScript tools and libraries

Comments are closed.