ECMAScript 6 and up in 2019
Tags: javascript, babel, compilers, ecmascript
Published: 2019-01-04 21:51:37

Do you - probably a JS developer reading this article right know - remember **ECMAScript 6** (ES6)? Released in 2015 ES6 standard for JavaScript language is what kick-started JS rapid development that can be appreciated today. Just face it - ES6 made JS fun to write again. With added **functionality** and some **syntactic sugar**, it made the web a place for more and more advanced websites and web apps. ES2016 (ES7), ES2017 and up only made it better with even more features (e.g. **async** / **await**) in a yearly release cycle. It also greatly impacted the JS ecosystem with frameworks like **Angular**, **React** and **Vue** becoming even more popular and dependent on. But ECMAScript is just a standard that needs to be implemented by different browsers' JS **engines**(e.g. **V8** from **Google Chrome**) and this is where things start to get less fun. Naturally, the fact that the standard has been **defined**, doesn't mean that it will be implemented right away. Old browsers' versions obviously will never get new features and on the newer ones, it may take a **long time** to implement them.

# Enter the compilers era

So, not everybody wants to wait this amount of time just to experience easier, better and modern coding solutions. That's why the JS **compilers** were created. These **transpilers** (term used interchangeably, but in my opinion better-describing the purpose of these tools) just take the code written in modern-style and change it to one compatible with more older browsers. This works almost all the time for new syntactic sugar but not really for modern language features and API, but it's enough to satisfy the needs of many developers. The most popular and well-known one is **Babel** - compiler implementing the latest and greatest **ES-Next** (a term for all new and up-coming ES versions) features ASAP and most likely a good friend of yours. Of course, solutions like this one left the JS community a bit divided between the ones wanting modern features and ones wanting performance. And here comes the point of this article. You can have code with great performance or code with modern syntax using transpiler, or the middle ground - **not really 100%** of the best from both worlds. Take a look at the code below utilizing ES6 syntax features like **const**, **let**, **arrow functions** and most notably - **for... of loops** and **rest/spread operator**:

```javascript
const uselessFunction = (...numbers) => {
    let sum = 0;
    for(const number of numbers) {
        sum += number;
    }
    return sum;
}
uselessFunction(1,2,3,4); //10

12345678
```

That's looking pretty fine, to be honest. It's a not-really-useful function for returning sum of all passed parameters. Now, the way you would probably implement this in **ES5** is:

```javascript
function uselessFunction(numbers) {
    var sum = 0;
    for(var i = 0; i < numbers.length; i++) {
        sum += numbers[i];
    }
    return sum;
}
uselessFunction([1,2,3,4]); //10

12345678
```

As you can see this is mostly the same code with the exceptions for a bit more code used for looping and the use of array instead of a list of parameters. It isn't really different from the example above. Considering you have updated your browser not that long ago and if you're not using **IE** (cause if you do then you must have some really important reasons behind this 🙃), then both of these snippets should work out-of-the-box when you execute them. Now, follow me in this particular scenario. You're considering yourself a modern JS developer and you do not start coding without Babel in place. And the fastest way to do this is just to install Babel and its default **ENV preset** without much hassle of configuring anything, and you start coding. When you finish writing your *uselessFunction* and you're reading to deploy it to production mode, something tickles you and you want to see the output of your modern code. And then... **this** happens:

```javascript
"use strict";

var uselessFunction = function uselessFunction() {
  for (var _len = arguments.length, numbers = Array(_len), _key = 0; _key < _len; _key++) {
    numbers[_key] = arguments[_key];
  }

  var sum = 0;
  for (var _iterator = numbers, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
    var _ref;

    if (_isArray) {
      if (_i >= _iterator.length) break;
      _ref = _iterator[_i++];
    } else {
      _i = _iterator.next();
      if (_i.done) break;
      _ref = _i.value;
    }

    var number = _ref;

    sum += number;
  }
  return sum;
};
uselessFunction(1, 2, 3, 4); //10

123456789101112131415161718192021222324252627
```

Now, let's end this terrible story right here and let's take a deeper look into **what has exactly happened**. Of course, the code above will be much, much slower than our ES5 hand-written alternative above. Not in the *uselessFunction* example really - it's too simple but most likely in more performance-demanding code. But, you can't really blame Babel for what has happened over here. It's just doing its job. You see, when using ENV preset without further configuration, you target **IE 11** and **Safari higher than 9** versions. This way Babel produces the output you can see above (not really the same as the ENV preset additionally adds error handling which isn't present here because I used **ES2015-loose** preset for a more fair comparison). This shows us how bad influence not properly configuring your compiler and not specifying lowest targeted versions of given browsers may have on the performance of your code.

# Welcome to 2019!

So, by now it's been almost **4 years** since the release of ECMAScript 6 / 2015 - happy new year BTW! 🎉 4 years is a really big amount of time especially looking at web development and technology in general. ES6 should be kind-of settled by now on most of the browsers and... **it mostly is**. But the habit of using compilers (sometimes without real need) has settled in minds of many developers. To help with this problem, here are some of the most popular ES6 features which have really great support in many browsers.

## Const & let variable declarations

It may come as a surprise for you but **const** and **let** keywords have really good cross-browser support. *Const* is supported completely or partially in almost **95%** of all web browsers - even **IE 11**! *Let* on the other hand comes right behind *Const* with around **90%** of browsers supporting it and **IE 11 having partial support**. Sadly these features aren't the ones that make our compiled code so big - they can be easily polyfilled with the *var* keyword.

## Arrow functions

Arrow functions are probably one of the most widely-used ES6 features. Providing a short form for writing functions - and especially callback ones - these also fix **this** context problem with **lexical binding**. With around **87%** of global support, you can freely use these when **not targeting IE 11** or **Safari 9.x**.

## Promises

Promises provide a better way of dealing with asynchronous code without falling into **callback hell**. They come with **89%** of support with an impressive achievement of being supported even in **Safari 7.1** - sadly, no such luck for IE. Interestingly, **async/await** syntactic sugar over promises (part of ES2017 specs) is supported in **85%** of all browsers. So, don't be scared to write async code in modern environments.

## Rest parameters / spread operator

Rest parameters have fine support of **87%** of global browsers. Actually, these are the main reason behind the big size of our Babel compiled code! 87% is not a bad score, but you can forget about supporting IE 11 or Safari 9.x without any polyfills.

## Classes

Now, classes are a new, better way of dealing with the *prototypical* nature of JavaScript by utilizing syntactic sweets again. Support for **87%** of used browsers including **Safari 9**.

So here you go with some examples or rather proofs that transpiler may not be really needed - at least in some cases. People are updating their browsers or even whole devices and as such the support will be only growing in a positive way. Keep in mind that we're talking only about clean JavaScript language here - no Web APIs or anything like that. If the number of examples above didn't really convince you - that's fine - at least I've tried. Raw data in percentage form is coming from [CanIuse](https://caniuse.com/), so if you want - check it out!

# Bottom line

The purpose of this whole post isn't to say that compilers, transpilers and etc. are bad - **not at all!** These are wonderful tools allowing you to write next-gen JavaScript today and, as JS is now in constant development, these are really useful! I'd rather want to point out at how important it is to know where your *bottom line* for backward support should be placed. Also, don't forget the code snippet above and take a closer look (at least sometimes) at the compiled code and your **.babelrc** file or whatever you're using.

Thanks for reading this post, and again - happy new year! 🎉 Lastly, I'm really looking forward to **ES2019**!