I started my career with .NET. I was a WPF developer and use Visual Studio as the primary IDE. Though I am a desktop application developer, I was aware of JavaScript programming. But I thought Javascript is a toy language and its primary purpose is to manipulate web pages.

But the evolution of Javascript is tremendous. When I started learning JavaScript throughout the learning i used to compare Javascript with c#.

Browser as runtime

Browser is for JavaScript as CLR is for .NET.

The runtime of .NET is CLR (Common Language Runtime) whereas the runtime of Javascript is browser. CLR cannot interpret C# as it is. CLR needs C# to be compiled down to intermediate language (IL) to interpret. But browsers can interpret Javascript as it is.

So it's obvious that Javascript is an interpreted language. But unlike other scripting languages JavaScript possess some characteristics of a compiled language.

Compile time errors

Unlike other interpreted languages Javascript produces errors upfront. Usually interpreted languages will be executed line by line. So if there is an error at line 100, all 99 lines will be executed before it gets aware of the issue in 100th line.

For an example consider the below shell script.

#!/bin/bash
# GNU bash, version 4.3.46

a="Hello"
b="World"
echo $a $b
int a = 2 + 2

The output of the above script will produce "Hello World" along with an error saying "int: Command not found". So it is able to execute valid statements ignoring the invalid statement. As an interpreted language, Javascript also expected to work in the same way, but it wont.

Consider the below Javascript code.

a="Hello"
b="World"
console.log(a + b)
int a = 2 + 2;

The above code will not produce any output except saying "Syntax error. Unexpected token" at line 4. The reason for this behavior is that Javascript undergo one other process before it gets executed - Parsing. The code will be transformed into abstract syntax tree. Abstract syntax trees are data structures widely used in compilers, due to their property of representing the structure of program code. An AST is usually the result of the syntax analysis phase of a compiler. Even thought Javascript is not compiled, it goes through one of the crucial step in a typical compilation process.

So it is not the right term to call these errors as compiler errors. Instead these are parser errors. And this behavior applicable only to syntax errors. So the process parsing can only catch syntax errors upfront. Other errors like type errors cannot be caught before and it will be thrown when that line is interpreted.

Kyle Simpson explains the behavior in below tweet.

Functions can be invoked before declaring

In a typical interpreted language, it is not possible to invoke a method before declaring it. Order of declaring and invoking a method does matter in interpreted languages. The below code will fail for the same reason. At the time of executing line number 4, it has no idea of the method "say_hello" and will fail.

#!/bin/bash
# GNU bash, version 4.3.46

say_hello

say_hello()
{
echo "Hello World"
}

But for surprise, Javascript never worried about the order of declaring and invoking a function. The below code will work without any issue.

sayHello()

function sayHello () {
console.log('Hello World!')
}

The reason for this behavior is Javascript go though a different process called hoisting before it gets executed. Hoisting is the default behavior of moving all the declarations at the top of the scope (to the top of the current script or the current function). In other words, a variable can be used before it has been declared. But keep in mind that hoisting can only move declarations to the top and not the assignments.

Babel - a Javascript compiler

If Javascript is not compiled, then why there are so many Javascript compilers around?

As any other programming languages, Javascript also has different versions. ECMA is the term used to specify a particular version of Javascript. In reality ECMA is specification and Javascript is one of the implementation of it. As we already discussed, browser is the runtime for Javascript.

When Javascript gets evolved with advanced features and new syntax, browsers should also evolve to support the new syntax. But not all the browsers support the latest version of Javascript. The level of compatibility is also not same across browsers. For example some browsers support 90% and some support 10%.

Javascript compilers now comes into picture. It transforms the non-compatible latest Javascript code into compatible code (mostly ES5) that can be recognised by all browsers. Ideally this process cannot be called compiling, since the input and output format has the same level of abstraction. So the actual term is Transpiler.

Conclusion

We can conclude saying that Javascript is an interpreted language. But Javascript is already advancing very fast and some of the modern browsers actually compile Javascript for better performance. V8 engine is one of that. The V8 Engine which is built by Google is open source and written in C++. This engine is used inside Google Chrome. Unlike the rest of the engines, however, V8 is also used for the popular Node.js runtime.

V8 was first designed to increase the performance of JavaScript execution inside web browsers. In order to obtain speed, V8 translates JavaScript code into more efficient machine code instead of using an interpreter. It compiles JavaScript code into machine code at execution by implementing a JIT (Just-In-Time) compiler like a lot of modern JavaScript engines do such as SpiderMonkey or Rhino (Mozilla). The main difference here is that V8 doesn’t produce byte code or any intermediate code.