the connection between JavaScript, ECMAScript, and Babel

by Stephanie Coates

While learning to code and getting familiar with JavaScript and React, Babel was one of those terms that I’d hear thrown around in conversation, but never actually knew much about what it was.

According to the Babel docs:

Babel is a JavaScript compiler; a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in old browsers or environments.

There’s a lot to unpack here!

Let’s start with the basics.

Babel is a tool used for frontend development, so browsers can read, understand, and display the JavaScript code that we write.

Curious about how browsers work behind the scenes? Check this out.

Is Babel absolutely necessary to create a web application? No. You could have a simple HTML file with CSS and JavaScript like this:

<!DOCTYPE html>
<html>
  <head>
    <title>My cool webpage</title>
    <style>
      body { background-color: yellow; }
    </style>
  </head>
  <body>
    <h1>Hello, World!</h1>
    <h4>Today is:</h4>
    <h4 id='date'></h4>
  </body>
    <script>
      document.getElementById('date').innerHTML = new Date().toDateString();
    </script>
</html>

And it would render in any browser just fine. Babel only comes into play when the JavaScript in your code can’t be understood by the browser.

Which JavaScript can be understood by browsers, and which JavaScript can’t?

The JavaScript in the above HTML file (within the <script> tags) is ES5-friendly syntax, which all browsers support. To understand what ES5 is, we need to dig into ECMAScript.

Ecma International, ECMA-262, and ECMAScript

Ecma International is an organization founded in 1961, which creates standards for technologies. While the organization creates standards for many, many different information and communication systems, the only standard we’re concerned about today is ECMA-262.

ECMA-262 contains the specification (in other words, the rules, details, and guidelines) for a general-purpose scripting language.

Think of ECMA-262 as the reference number for the ECMAScript spec. Scripting languages must abide by this spec to be considered ECMAScript compliant.

Which languages can be considered general-purpose scripting languages?

Scripting languages are programming languages designed specifically to manipulate an existing system. JavaScript is one of them. For example, JavaScript is the scripting language and the JavaScript runtime environment is the existing system it performs actions on.

On the client side, the runtime environment would be the web broswer - host objects like windows and HTML documents are made available by the web broswer to be manipulated by the scripts. These host objects are not a part of the core JavaScript language - instead, they’re web APIs provided by the browser.

In contrast, for server-side JS, the JavaScript runtime is Node.js and server-related host objects like the file system, processes, and requests are available in Node.js for the JavaScript scripts to act upon.

While JavaScript isn’t the only implementation of the ECMAScript standard (others include ActionScript and JScript), it’s the most popular by far.

ES1 vs ES5 vs ES6 vs ES2015

Now that we understand the ECMAScript spec, it’s time to talk about the different editions of ECMAScript.

If you’ve read any articles or documentation related to JavaScript, you’ve inevitably seen the term ES. ES5, ES2015, ES6, ES7, etc. ES is simply short for ECMAScript, and these terms reference the different published editions of ECMAScript. There are currently 10 editions:

  • ES1 (June 1997): First edition
  • ES2 (June 1998): Editorial changes to align the spec with the ISO/IEC 16262 international standard
  • ES3 (December 1999): Adds RegExp, better string handling try/catch blocks, tighter error definition, and numeric output formatting
  • ES4: Abandoned due to political differences concerning the language. Some proposed features were completely scrapped, while others were incorporated into later editions.

    after a nearly 10 year hiatus…

  • ES5 (December 2009): Adds strict mode, getters and setters, JSON support, and improvements on object properties
  • ES2015/ES6 (June 2015): Fully aligned the ECMAScript standard with the 3rd edition of the international standard ISO/IEC 16262. Added class declarations, import syntax for ES6 modules, iterators and for...of loops, Python-style generators, fat arrow functions, default parameter values, let and const keywords, promises, template literals, and more.

    this gets a bit confusing. The committee overseeing ECMAScript decided to move to annual updates starting with ES6, so the edition was renamed from ES6 to ES2015 to reflect the year of the release. Both names are still common to refer to this edition and mean the same thing.

  • ES2016/ES7 (June 2016): Adds block scoping, destructuring, the exponentiation variable (**), and Array.prototype.includes() method.
  • ES2017/ES8 (June 2017): Adds async/await constructions to work with generators and promises, string padding, new Object properties, and shared memory
  • ES2018/ES9 (June 2018): Adds rest/spread operators (...identifier), asynchronous iteration, promise.finally syntax, and additions to RegExp
  • ES2019/ES10 (June 2019): Adds new Array methods including Array.prototype.flat, Array.prototype.flatMap, and changes to existing methods such as Array.sort and Object.fromEntries

Developers often want to use the shiny new features that come with ES6/ES2015, ES7/ES2016, and so on. However, they should be concerned about cross-browser compatibility for their web apps.

JavaScript Engines and ES edition compatibility

Before JavaScript code can manipulate the runtime environment environment, a JS engine is needed to understand, interpret, and execute the JS code. Chrome has the V8 engine, Firefox has SpiderMonkey, and Edge has Chakra.

Just as there are different dialects within in the English language (people in different regions have different words, expressions, and syntax rules they are familiar with), there’s variability when it comes to browser support from engine to engine.

Even though all JavaScript engines within browsers understand JavaScript in general, some browsers have a greater understanding of the language (specifically new syntax from recent ECMAScript edition releases) than others.

ES3 is fully understood and supported in all browsers.

ES5 is fully understood and supported in all modern browsers. This includes Chrome, Firefox, IE, IE/Edge, Safari, and Opera.

ES6/ES2015 is supported by Chrome, Firefox, Edge, Safari, and Opera. Internet Explorer does not support ES2015.

ES7/ES2016 is only supported by Chrome and Opera.

ECMAScript editions beyond ES2016 are not currently supported by any browsers.

What does this mean? If you wrote JavaScript syntax that fell within the ES6/ES2015 specification (using fat arrow functions, let and const variables, or the import keyword) and tried to directly run it within an IE web browser, it wouldn’t work. IE doesn’t understand how to interpret that syntax, and your application would break.

Similarly, if you use the spread (...) operator, which hails from ES2018/ES9 syntax, and run it directly in the Chrome browser, it won’t work.

ECMAScript editions are released more often than browsers are able to implement features to parse the new syntax. This is where transpilers, like Babel, come in.

Transpiling code to be backwards compatible

When we ship code, we want it to work in all modern browsers. Using ES6/ES2015 syntax results in a better coding experience for the developer, however, it’d be a bummer if all IE browser users were unable to load our application. The same goes for even newer editions, and a wider array of incompatible browsers.

Babel gives us the best of both worlds. We can use updated syntax and rest easy knowing it can be interpreted by all modern browsers. Babel is able to understand and convert all current

In a sense, Babel acts as a dictionary - when our final application code is ready to deploy to a server, we can set up Babel to transpile, or translate, ES2015+ code to simpler, widely-understood syntax all browsers can read during the build process.

A real-world example:

You’re 12 years old, reading a kindle book that has a lot of complex words in it. You read the following sentence:

She was nonplussed at the idea.

What the heck does nonplussed mean? Big words like this significantly affect your ability to comprehend the book.

If Babel was part of the scenario, the transpilation step would happen before this book even arrived in your hands. The author still writes the book in her complex words, but Babel, the middleman, acts as a dictionary and translates the words into simpler terms so 12-year-old you can understand it and still enjoy the novel as a whole. When you read the transpiled book this time, the sentence appears as follows:

The idea surprised and confused her so much that she was unsure how to react.

It’s more widely-understood English. Much better. In this example, you’re the web browser, the original book is ES6/ES2015 syntax, and the translated/transpiled book is code after Babel works its magic to make the words understandable no matter who the audience.

Compilers vs transpilers

I’ve mainly used the term transpiler to describe Babel so far, however, the Babel docs specify that it’ a compiler. What’s the difference?

A transpiler is a type of compiler.

Compilers, in general, convert one language to another at lower abstraction level. For example, it takes Java code and turns it into 0s and 1s for the computer to understand.

Transpilers (also known as source-to-source compilers) convert a language to something else, but typically at the same abstraction level. Transpilers convert Typescript to Javascript, sass to css, and in our case, ES6/ES2015 Javascript to ES5 Javascript.

Babel has an online interactive tool that shows how it manipulates ES5+ code and what the transpiled, browser-readable code turns out as. Play with transpiler here.

Other than converting modern JS syntax to ES5-friendly code, Babel has additional features as well, including polyfills and source code transformations. It’s all explained in the Babel docs.

How do Babel and React relate to each other?

Within the React developer community, Babel often comes up.

We’ve talked about how to transpile different ECMAScript editions of JavaScript, but what about React and JSX?

Babel offers a react-preset (a bundle of plugins) that transpiles JSX and React-specific syntax into ES5 JavaScript any browser can interpret. Given that no browsers can currently interpret JSX natively, Babel (or another transpilation tool) is necessary to run React code in the browser.

Hopefully this clears up the connection between browsers, JavaScript, ECMAScript, and compilers/transpilers like Babel. Thanks for reading!