Sounds cool, can I use it?
ES2015 comes with a bunch of cool new features that we will briefly discuss later. Now that these features are basically frozen for this iteration, it’s safe to start working with them in full scale production applications.
Even more, I encourage you to migrate your old code as soon as you can to the new standard, because any line of code that you write using the previous ES5 standard is obsolete from day 1.
“The future is already here — it’s just not very evenly distributed.” — William Gibson
As you can see in the compatibility table, ES2015 is being adopted at a fast pace by all browsers, even Safari and Microsoft Edge (the fancy name they came up with for the new version of IE). Not all functionality is implemented yet, but you can already use a good chunk of the new features directly in the browser.
However, I don’t advise you to write ES2015 code and then run it in directly in browser. Say hello to babel.
So we write ES2015 code today, the code gets transpiled into ES5, which is almost 100% supported in most modern browsers. Once most of the major functionalities offered by ES2015 are implemented in the modern browsers, we just get rid of the babel transpiler from our build process. So with a single step we bring our live code to the ES2015 standard.
I remember being fascinated by the amount of new stuff that ES6 promised to bring, so if you want a complete guide for the new features I can advise you to follow these “tutorials”:
Now let’s discuss some of my favorite new features.
Arrow functions allow you to write anonymous functions in a much more compact way, dropping a lot of boilerplate code. This paves the way for functional style programming, and allows programmers to keep their sanity while reading functional code written by others.
The cool part with arrow functions is that you never have the write the word function — except in the cases in which you actually need a named function. Then you read about the new enhanced object literal notation and you realize that the word function is probably going to be forgotten soon.
As you probably figured it out by now, “let” is equivalent with “var”, but it is block-scoped., This means that it does not exist outside the block in which it is defined.
On the other hand, “const” allows you to define a variable with a fixed value. It can only get a value when it is created, and any subsequent assignment to a “const” has no effect. This is very important in terms of expressiveness because you can declare all variables that you do not modify in your code with “const” and all the others with “let.” This way, any value that has the potential to mutate in your code is easily trackable from the beginning. If all your variables are constants (no pun intended) you don’t need to worry about side effects or unwanted state mutations.
Talking about expressiveness, destructuring offers tons of ways of saying more with fewer lines of code. This feature basically does pattern matching on objects and arrays, allowing you to quickly access parts of them.
With destructuring, you no longer need to create variables which point to certain properties or to sub-objects of the function parameter, like in the fullName() example above. Also it is easier to return multiple values from one function without writing too many lines of code. Destructuring is fun when it is combined with the new ways of handling function parameters: default parameters and the rest and spread operators.
Function Parameters — Default, Rest, Spread
Default parameters are pretty straight-forward, and are already present in many programming languages, so nothing extraordinary here. However the rest and the spread operators allow you to handle function parameters in any way you want.
Ok, we’ve been playing around with the syntax, we’ve made some cool functional style programming snippets, let’s dig deep into one of the most interesting features offered by ES2015, namely generators. Very briefly explained, generators are factory functions for iterators. Still confused? I was too, but let’s look at an example
So what is happening here? A generator is basically a function which can be stopped at any time and resumed afterwards. The generator is stopped when the yield statement is executed and it returns whatever value we place next to the yield statement. We use the next() function call to go one step at a time, collecting the value yielded by the generator.
As an additional feature, you can pass a parameter to the next() function and that parameter is considered the return of the yield statement in the generator. So we basically have a two-way communication between the generator function and the outside world.
The big deal with generators is their potential to be used in the parts of the code that handle asynchronous calls. Imagine the situation in which you need to perform 3 distinct api calls in a particular order, always using the result of one call as parameter to the next call. Imagine how that code would look like with callbacks or even with promises.
What if we can do something like this instead?
There are already working solutions with allow you to write sequential async calls with generators and promises. As an example, you can checkout this article which shows a similar solution.
Of course there are many other cool features like string templates, native promises, AMD-style modules, new functions added on the prototypes of Number, String, Array and Object and many more. But I presented here the ones which I consider the most useful in regular coding tasks. However, there’s a dark twist with one of the new features that I want to discuss.
I bet 50% of the people that read the specs were looking forward to this, while the other 50% were saying: “But … why???” I fall into the second category here.
ES2015 brings a sugaring syntax which uses prototypal object creation in the back. Here’s an example:
My standard interview contains the following set of questions I ask in succession:
- “Are classes mandatory in OOP?”
- “Does it have classes?”
Embrace Functional Programming
With const and let you are able to add another level of expressiveness to all your variables. You will probably avoid using var from this point on. Arrow functions combined with classic iterator functions are letting you write functional reactive programming, basically creating streams of functionality.
Your code becomes more succinct, more functional and less stateful. This also means that your code is easier to test and to maintain, and also far less prone to bugs, and feature pure functions, immutable data. There’s a lot of content out there on the benefits of functional programming, and I think that iterating over those points again doesn’t make sense in the scope of this article.
Working with Babel isn’t that hard, and I encourage you to start doing it today. Remember, code that you write today using ES5 syntax is obsolete. Fair and simple.
ES2015 was a huge release with a lot of changes. The TC39 committee started with a different approach and they will standardize new features each year, basically splitting what was originally intended to be implemented as ES7 into smaller chunks.
Usually all future features are called generically ESnext, in case you see this anywhere. With Babel, you can even play with some of these future features today!
Here are some articles I recommend reading regarding ESnext features: