How JavaScript Works: The JavaScript Engine

And How a "Toy" Language Became Popular

How JavaScript Works: The JavaScript Engine

Dear JavaScript community, I have a confession to make. I once called JavaScript a toy language. I know, I know, I'm sorry. We can all agree, though, that JavaScript's rise to one of the most popular languages of today didn't happen in a day or 10.

A Brief History of JavaScript

During the first browser war, competition for dominance in the usage share of web browsers was fierce, which led to browser vendors adopting a rapid development of features. Through a license agreement, Netscape, the company behind the Netscape Navigator browser, added support for Java in their flagship browser. Netscape, however, saw the need for another scripting language that would allow for a more dynamic web. This scripting language would act as a "glue language" for web designers and hobbyists to assemble components and automate their interactions. Java, on the other hand, would be the "component language" used by higher-priced programmers.

Netscape recruited Brendan Eich in 1995 to develop this scripting language. Brendan Eich was under marketing orders to make this scripting language look like Java but not behave the same. Thus Brendan Eich didn't adopt existing scripting languages like Perl and Python. He also had a strict time frame to develop the language and therefore wrote the language in 10 days. This scripting language is what we now know as JavaScript.

As we know it today, JavaScript has evolved into a powerful tool that can write apps everywhere. It is also not regarded as a language for just hobbyists. But how did JavaScript gain so much power and popularity? Enter the JavaScript engine.

Is JavaScript an Interpreted or Compiled Language?

A JavaScript engine is just a fancy term for a program that executes JavaScript code.

Computers don't understand JavaScript; they only understand 1's and 0's, machine code. The work of a JavaScript engine is to translate our code into a language that the computer can understand.

There are two primary ways this code execution can happen: via an interpreter or compiler.

An interpreter runs through the code and executes it line by line. On the other hand, a compiler converts the entire code into machine code (via a compilation step) to create an executable file that the computer can then execute.

The advantage of using an interpreter is that it is quick to get up and running as there is no compilation step involved. The disadvantage of an interpreter, however, is that it lacks optimization.

While a compiler might involve a compilation step, it has the advantage of optimizing code. Thus, the code will run faster.

Okay, I digressed. But back to our question, is JavaScript interpreted or compiled? The answer is it depends. It depends on the implementation of the JavaScript engine in use, and there are many JavaScript engines. This Wikipedia page lists the most common JavaScript engines, also called ECMAScript engines because all engines must conform to the ECMAScript standard.

When Brendan Eich wrote JavaScript in 1995, he also wrote the first JavaScript engine. This engine was just an interpreter, capable of running the programs at that time.

During the 2000s, the face of the web had changed significantly. Microsoft had invented XMLHttpRequest that would allow JavaScript to communicate with servers. JavaScript was no longer just a language for "gluing" components.

During that same time, the second browser wars began, and it was apparent that the winner of this war would have the most performant browser. Using a JavaScript engine that was just an interpreter couldn't keep up with the needs of the new times. There was a need to compile the JavaScript code to gain the benefits of optimization for faster speeds.

In 2009, Firefox released version 3.5 that used a Just-in-Time(JIT) compilation called TraceMonkey in their SpiderMonkey engine. Google and other web browsers followed suit with Google releasing the V8 engine.

With a JIT compiler, the idea is to marry the best of an interpreter and a compiler. We get the ability to execute our program instantly (cause who has the time to wait for a web page to compile). And while the engine executes the program, it runs a compilation of the program simultaneously. In the end, we get a program that runs instantly but also gets optimization benefits for faster performance.

While it may seem that JavaScript engines are built solely for web browsers, this is not true. JavaScript engines are independent of browsers. Thus, projects such as Node.js have allowed for JavaScript code execution outside of the web browser.

Inside the JavaScript Engine

All JavaScript engines contain a call stack and a heap. The call stack executes JavaScript code using an execution context (we will look at the concept of execution contexts in another article), while the heap stores objects in memory.

The JavaScript Engine

How Just-in-Time (JIT) Compilation Works in JavaScript

Remember that there are many JavaScript engines, and thus we will focus on the popular V8 engine.

The V8 Engine

The first step of the execution involves parsing the JavaScript file and breaking down the code into tokens to identify meaning from the code. These tokens make up the Abstract Syntax Tree (AST).

The generated AST is then compiled into native code by the Full CodeGen compiler. Using a compiler instead of an interpreter at this stage is a critical difference between the V8 engine and other engines. Other engines use an interpreter, producing bytecode instead. The Full CodeGen compiler is fast; however, it generates unoptimized code.

Meanwhile, the profiler keeps an eye on the code to spot hot areas, sections of code that execute repeatedly. When hot code is spotted, the execution takes the path of optimization, replacing bits of the native code that could use optimization.

JavaScript's Future

JavaScript's evolution took time, but it is here to stay. Brendan Eich once admitted that the quirks of JavaScript were due to the short time he had to develop a prototype. While some developers complain about these quirks, programmers should note that many programming languages have quirks. These quirks are not the reason that JavaScript seemed limited. The technologies available to JavaScript at the time of its invention limited its capabilities. If you make a tool accessible to as many people as possible, however, innovation will follow.

With the development of JIT-compiled engines that allow for optimized code, we can now write faster and powerful applications anywhere. While JavaScript might have started its journey as a language for hobbyists, it has rightfully earned its place as one of today's most popular programming languages.