JavaScript Interpreted or Compiled? The Debate is Over.

Subscribe to my newsletter and never miss my upcoming articles

Introduction

As a beginner to the JavaScript programming language, I had faced this question so may times:

Does JavaScript Interprets the Source code or it really Compiles?

Many of the answers that I found on the internet made me as Confused as,

confused.gif From https://giphy.com/

Few of the other online posts, discussions, blogs shed some bright lights on it. I thought it would be better to put it in a concise and easy to understand manner here.

This is the first post of the series, JavaScript: Cracking the Nuts. Hope you enjoy reading it.

JavaScript Interpreted or Compiled?

In general, JavaScript is categorized as a dynamic or interpreted language. There are lots of misunderstanding about this fact. We need to ask and find the answers of,

  • Is it completely fair to say, JavaScript is an Interpreted Language?
  • What is the difference between an Interpreter and a Compiler?

An interpreter is a computer program that directly executes instructions written in a programming or scripting language, without requiring them previously to have been compiled into a machine language program. It translates one Statement at a time.

Whereas,

A compiler is computer software that transforms computer code written in one programming language (the source language, like JavaScript, etc) into another programming language (the target language, like machine code).

First thing to understand, Computer doesn't understand the programming languages directly. Every programming languages got their own syntax, grammar and structure. No matter what Programming languages(JavaScript, Python, Java, etc) we are writing the code with, it has to be translated into something that machine(Computer) understands.

The most important fact here is, how does the JavaScript source code goes through the journey of becoming a machine understandable language? JavaScript Engine performs many of the steps(in fact, more cleaner and sophisticated ways) that a typical Compiler would perform in compiling a source code.

In JavaScript, the source code typically goes through following phases before it is executed,

  • Tokenizing: Breaking up a source code string into meaningful chunks called, Tokens. For example, the source code var age = 7; can be tokenize as, var, age, =, 7 and, ;.
  • Parsing: Parsing is a methodology to take the array of Tokens as an input and, turn it into a tree of nested elements that is understood by the grammar of the programming language. This tree is called, Abstract Syntax Tree(AST).
  • Code Generation: In this phase, the AST used as input and an executable byte-code is generated that is understood by the environment(or platform) where the executable code will be running. The executable byte-code then refined/converted even further by the optimizing JIT (Just-In-Time) compiler.

"A Picture worth thousand words". Here is a pictorial representation of how these three phases take place:

execution_steps.gif JavaScript Code Compilation Steps

You can use the AST Explorer tool to see how code written by you gets parsed into an Abstract Syntax Tree(AST).

ast.png Created using AST Explorer

Conclusion

To conclude, JavaScript code indeed gets compiled. It is more closer to be Compiled than Interpreted. It is compiled everytime. Next time, if someone asks the question, Does JavaScript really Compiles? The answer is, a loud YES. After the compilation process produces a binary byte code, JS virtual machine executes it.

Unlike other programming languages like, Java, the compilation doesn't take place at the build time. The three phases described above are not the only things happen to Compile JavaScript Source code. JavaScript engine needs to perform lots of optimizations steps to tackle performance issues.

As a developer, we are abstracted away from all of these. We will see more in-depth topics about JavaScript Engine in the future post of the series.

It's time. Let's call it out, JS is a Compiled Language.

Resources

The resource I recommend for this subject is,

This is an excellent read if you are looking for more detailed explanations. You can start reading from this section directly. My favorite part from this read is,

So what do "parsed" languages have in common with "compiled" languages? First, all compiled languages are parsed. So a parsed language is quite a ways down the road toward being compiled already. In classic compilation theory, the last remaining step after parsing is code generation: producing an executable form.

Credit


If it was useful to you, please Like/Share so that, it reaches others as well. To get e-mail notification on my latest posts, please subscribe to my blog by hitting the Subscribe button at the top of the page.

In the next post of the series, I'll be explaining about another fundamental concept called, JavaScript Execution Context, like never before! Stay Tuned.

j's photo

based on this definition php, python, perl are also compiled languages. actually every language that has a VM is compiled.

I know the definition changed over the years, but the reason those languages are not considered 'compiled' is the preprocessing/optimization step not the transformation itself. But ofc we could argue esp since graal in Java now supports compiled javascript to java-vm code and other things.

also since ES6 gets 'transpiled' it gets fuzzy quick. still it remains an interpreted language with JIT qualities to me.

Show +2 replies
Tapas Adhikary's photo

☝ UI/UX Enthusiast | 💻 Work @MicroFocus | ✍️ Blogger | 👨‍🏫 Mentor | 🎤 Speaker | 🍟 Foodie

j No problem at all.. Glad to have this healthy discussion and hoping others will benefit too.

BTW.. All the best for your Compiler Development project. 👍

j's photo

stuff ;)

Mario Giambanco's photo

The gist of your argument (IMO) is that because JS follows "some" similar processes of a compiler (tokenizing, specifically) that it is in fact, compiled. The problem with this argument, as j stated, is that all languages would fall into this and that's not correct.

When anything is actually compiled, it's expected to act and operate identically on all hardware and os's it's compiled for. If I write an iOS app in Swift and it's compiled for iOS, I can expect that app to work exactly the same on any platform that can run an iOS app (obviously, different versions of iOS may produce different results but that's getting off topic)

VS Chrome has a Javascript engine, Safari has a Javascript engine, Firefox has a .... Javascript engine. And while some of these browsers may use the same engine as a base, this is also why "sometimes" things work fine in Chrome and IE and sometimes they don't. They are all processing the JS as it comes in and "interpreting" it as they're designed to do so.

In a compiled JS app - they wouldn't. The code would be executed and the result is the result every time.

Another point, going further down this rabbit hole - a compiled language usually means the OS or the machine itself is executing the code directly. If JS was compiled, there would be no reason for the browser to execute and interpret the code. Now you could say Chrome is the "os" in this case and Chrome is executing the compiled code but IMO that's a stretch. There is still an engine looping through and interpreting the code. iOS, MacOS, Windows, Linux, et all are not interpreting compiled code - they're simply executing it.

j's photo

stuff ;)

Another point, going further down this rabbit hole - a compiled language usually means the OS or the machine itself is executing the code directly.

java is compiled, c# is compiled both are not running natively. Although the new javac coming up will allow native AOT compilation.

In a compiled JS app - they wouldn't. The code would be executed and the result is the result every time.

that's a tricky one. it depends on the linking process. If I use dynamic linking (.dll, .so) I actually use foreign ABIs in my compiled code so they could fail from system to system. at least in C, C++, Rust I got those problems I cannot talk about the other ones.

Also it would depend on the compile target that's the main reason why the VM exists so the translation between Highlevel and lowlevel isn't that complicated. Usually it's Highlevel -> stackmachine / VM -> asm target -> machine language

before I was writing my own compiler I would've taken a similar stance to be fair. It really gets tricky and hard to answer esp since JIT which basically takes the compiled code (VM/Interpreter -> fun fact Java starts 'somewhat interpreted' usually), creates statistical data about it and changes the execution layout and compiles 'more and more, based on the behaviour'

Still compiled as you actually mentions would mean that the VM code is 'listed' (compilare). But even here we could argue.

I don't wanna bore you further. it is just really tricky and it's like quantum physics and chemistry at which point do they merge? I really prefer pointing at the 'preprocessing' shit since a jvm always starts with the VM code and js just 'can' start with the VM code (caching).

that's the core difference and actually the 'interpreter' debate is off because we're actually debating 'script' vs 'compiled' to some degree.

anyhow ... bla