2015-11-11

I recently went to HTML5 Dev conference in San Francisco. Half of the talks I went to were about ES6 or, as it’s now called officially, ECMAScript2015. I prefer the more succinct ES6 though.

This essay will give you a quick introduction to ES6. If you don’t know what is ES6, it’s a new JavaScript implementation. If you’re a busy JavaScript software engineer (and who is not?), then proceed reading to learn the best 10 features of the new generation of the most popular programming language—JavaScript.

Here’s the list of the top 10 best ES6 features for a busy software engineer (in no particular order):

Default Parameters in ES6

Template Literals in ES6

Multi-line Strings in ES6

Destructuring Assignment in ES6

Enhanced Object Literals in ES6

Arrow Functions in ES6

Promises in ES6

Block-Scoped Constructs Let and Const

Classes in ES6

Modules in ES6

Disclaimer: the list if highly biased and subjective. It is in no way was intended to diminish usefulness of other ES6 features, which didn’t make it to the list simply because I had to limit the number to 10.

First, a bit of history because those who don’t know the history can’t make it. This is a brief JavaScript timeline:

1995: JavaScript is born as LiveScript

1997: ECMAScript standard is established

1999: ES3 comes out and IE5 is all the rage

2000–2005: XMLHttpRequest, a.k.a. AJAX, gains popularity in app such as Outlook Web Access (2000) and Oddpost (2002), Gmail (2004) and Google Maps (2005).

2009: ES5 comes out (this is what most of us use now) with forEach, Object.keys, Object.create (specially for Douglas Crockford), and standard JSON

2015: ES6/ECMAScript2015 comes out; it has mostly syntactic sugar, because people weren’t able to agree on anything more ground breaking (ES7?)

Enough with history, let’s get to the business of coding.

1. Default Parameters in ES6

Remember we had to do these statements to define default parameters:

They were okay until the value was 0 and because 0 is falsy in JavaScript it would default to the hard-coded value instead of becoming the value itself. Of course, who needs 0 as a value (#sarcasmfont), so we just ignored this flaw and used the logic OR anyway… No more! In ES6, we can put the default values right in the signature of the functions:

By the way, this syntax is similar to Ruby!

2. Template Literals in ES6

Template literals or interpolation in other languages is a way to output variables in the string. So in ES5 we had to break the string like this:

Luckily, in ES6 we can use a new syntax ${NAME} inside of the back-ticked string:

3. Multi-line Strings in ES6

Another yummy syntactic sugar is multi-line string. In ES5, we had to use one of these approaches:

While in ES6, simply utilize the backticks:

4. Destructuring Assignment in ES6

Destructuring can be a harder concept to grasp, because there’s some magic going on… let’s say you have simple assignments where keys house and mouse are variables house and mouse:

Other examples of destructuring assignments (from Node.js):

In ES6, we can replace the ES5 code above with these statements:

This also works with arrays. Crazy!

It might take some time to get use to the destructuring assignment syntax, but it’s a sweet sugarcoating.

5. Enhanced Object Literals in ES6

What you can do with object literals now is mind blowing! We went from a glorified version of JSON in ES5 to something closely resembling classes in ES6.

Here’s a typical ES5 object literal with some methods and attributes/properties:

If we want to be fancy, we can inherit from serviceBase by making it the prototype with the Object.create method:

I know, accountServiceES5ObjectCreate and accountServiceES5 are NOT totally identical, because one object (accountServiceES5) will have the properties in the __proto__ object as shown below:



Enhanced Object Literals in ES6

But for the sake of the example, we’ll consider them similar. So in ES6 object literal, there are shorthands for assignment getAccounts: getAccounts, becomes just getAccounts,. Also, we set the prototype right there in the __proto__`` property which makes sense (not‘proto’` though:

Also, we can invoke super and have dynamic keys (valueOf_1_2_3):



Enhanced Object Literals in ES6 II

This is a great enhancement to good old object literals!

6. Arrow Functions in ES6

This is probably one feature I waited the most. I love CoffeeScript for its fat arrows. Now we have them in ES6. The fat arrows are amazing because they would make your this behave properly, i.e., this will have the same value as in the context of the function—it won’t mutate. The mutation typically happens each time you create a closure.

Using arrows functions in ES6 allows us to stop using that = this or self = this or _this = this or .bind(this). For example, this code in ES5 is ugly:

Sadly, the ES6 committee decided that having skinny arrows is too much of a good thing for us and they left us with a verbose old function instead. (Skinny arrow in CoffeeScript works like regular function in ES5 and ES6).

Here’s another example in which we use call to pass the context to the logUpperCase() function in ES5:

While in ES6, we don’t need to mess around with _this:

Note that you can mix and match old function with => in ES6 as you see fit. And when an arrow function is used with one line statement, it becomes an expression, i.e,. it will implicitly return the result of that single statement. If you have more than one line, then you’ll need to use return explicitly.

This ES5 code is creating an array from the messages array:

Will become this in ES6:

Notice that I used the string templates? Another feature from CoffeeScript… I love them!

The parenthesis () are optional for single params in an arrow function signature. You need them when you use more than one param.

In ES5 the code has function with explicit return:

And more eloquent version of the code in ES6 with parenthesis around params and implicit return:

7. Promises in ES6

Promises have been a controversial topic. There were a lot of promise implementations with slightly different syntax. q, bluebird, deferred.js, vow, avow, jquery deferred to name just a few. Others said we don’t need promises and can just use async, generators, callbacks, etc. Gladly, there’s a standard Promise implementation in ES6 now!

Let’s consider a rather trivial example of a delayed asynchronous execution with setTimeout():

We can re-write the code in ES6 with Promise:

Or with ES6 arrow functions:

So far, we’ve increased the number of lines of code from three to five without any obvious benefit. That’s right. The benefit will come if we have more nested logic inside of the setTimeout() callback:

Can be re-written with ES6 promises:

Still not convinced that Promises are better than regular callbacks? Me neither. I think once you got the idea of callbacks and wrap your head around them, then there’s no need for additional complexity of promises.

Nevertheless, ES6 has Promises for those of you who adore them. Promises have a fail-and-catch-all callback as well which is a nice feature. Take a look at this post for more info on promises: Introduction to ES6 Promises.

8. Block-Scoped Constructs Let and Const

You might have already seen the weird sounding let in ES6 code. I remember the first time I was in London, I was confused by all those TO LET signs. The ES6 let has nothing to do with renting. This is not a sugarcoating feature. It’s more intricate. let is a new var which allows to scope the variable to the blocks. We define blocks by the curly braces. In ES5, the blocks did NOTHING to the vars:

The result will be 1000. Wow! That’s a really bad bug. In ES6, we use let to restrict the scope to the blocks. Vars are function scoped.

The value is 0, because the if block also has let. If it had nothing (amount=1), then the expression would have been 1.

When it comes to const, things are easier; it’s just an immutable, and it’s also block-scoped like let. Just to demonstrate, here are a bunch of constants and they all are okay because they belong to different blocks:

In my humble opinion, let and const overcomplicate the language. Without them we had only one behavior, now there are multiple scenarios to consider. ;-(

9. Classes in ES6

If you love object-oriented programming (OOP), then you’ll love this feature. It makes writing classes and inheriting from them as easy as liking a comment on Facebook.

Classes creation and usage in ES5 was a pain in the rear, because there wasn’t a keyword class (it was reserved but did nothing). In addition to that, lots of inheritance patterns like pseudo classical, classical, functional just added to the confusion, pouring gasoline on the fire of religious JavaScript wars.

I won’t show you how to write a class (yes, yes, there are classes, objects inherit from objects) in ES5, because there are many flavors. Let’s take a look at the ES6 example right away. I can tell you that the ES6 class will use prototypes, not the function factory approach. We have a class baseModel in which we can define a constructor and a getName() method:

Notice that I’m using default parameter values for options and data. Also, method names don’t need to have the word function or the colon (:) anymore. The other big difference is that you can’t assign properties this.NAME the same way as methods, i.e., you can’t say name at the same indentation level as a method. To set the value of a property, simply assign a value in the constructor.

The AccountModel inherits from baseModel with class NAME extends PARENT_NAME:

To call the parent constructor, effortlessly invoke super() with params:

If you want to be really fancy, you can set up a getter like this and accountsData will be a property:

So how do you actually use this abracadabra? It’s as easy as tricking a three-year old into thinking Santa Claus is real:

In case you’re wondering, the output is:

10. Modules in ES6

As you might now, there were no native modules support in JavaScript before ES6. People came up with AMD, RequireJS, CommonJS and other workarounds. Now there are modules with import and export operands.

In ES5 you would use <script> tags with IIFE, or some library like AMD, while in ES6 you can expose your class with export. I am a Node.js guy, so I’ll use CommonJS which is also a Node.js syntax. It’s straightforward to use CommonJS on the browser with the Browserify bunder. Let’s say we have port variable and getAccounts method in ES5 module.js:

In ES5 main.js, we would require('module') that dependency:

In ES6, we would use export and import. For example, this is our library in the ES6 module.js file:

In the importer ES6 file main.js, we use import {name} from 'my-module' syntax. For example,

Or we can import everything as a variable service in main.js:

Personally, I find the ES6 modules confusing. Yes, they are more eloquent, but Node.js modules won’t change anytime soon. It’s better to have only one style for browser and server JavaScript, so I’ll stick with CommonJS/Node.js style for now.

The support for ES6 modules in the browsers are not coming anytime soon (as of this writing), so you’ll need something like jspm to use ES6 modules.

For more information and examples on ES6 modules, take a look at this text. No matter what, write modular JavaScript!

How to Use ES6 Today (Babel)

ES6 is finalized, but not fully supported by all browsers (e.g., ES6 Firefox support). To use ES6 today, get a compiler like Babel. You can run it as a standalone tool or use with your build system. There are Babel plugins for Grunt, Gulp and Webpack.



How to Use ES6 Today (Babel)

Here’s a Gulp example. Install the plugin:

In gulpfile.js, define a task build that takes src/app.js and compiles it into the build folder:

Node.js and ES6

For Node.js, you can compile your Node.js files with a build tool or use a standalone Babel module babel-core. To install it,

Then in Node.js, you call this function:

Summary of ES6 Things

There are many other noteworthy ES6 features which you probably won’t use (at least not right away). In no particular order:

New Math, Number, String, Array and Object methods

Binary and octal number types

Default rest spread

For of comprehensions (hello again mighty CoffeeScript!)

Symbols

Tail calls

Generators

New data structures like Map and Set

For overachievers who can’t stop learning about ES6, like some people who can’t stop after the first potato chip (just one more!), here’s the list for further reading:

ES6 Cheatsheet

Understanding ECMAScript 6 by Nicolas Zakas book

Exploring ES6 by Dr. Axel Rauschmayer

Show more