ECMAScript 6 - Let's see what it has to offer

Introduction

Unless you've been living under a rock, the upcoming standard for JavaScript: ECMAScript 6 should be no surprise. In the end, all of this commotion boils down to something very basic: ES6 brings a LOT of good features (mostly syntactic sugar) for better, more beautiful code.

EC6, aka Harmony is essentially the sweeter, and the friendlier brother of JavaScript (ECMAScript 5, or before) and this bad bou comes with some kick-ass features (yes, we'll have a look at them here.)

But, but, but. (Yes, there is always a 'but') All of this goodness comes for a price: native support for EC6 may take a while. But that doesn't stop us from using it today, now does it? The good ol' saying very eloquently describes my point:

soccer has a goalie, but that doesn't stop you from scoring a goal

Now, there are some websites like this one by Thomas Lahn which provide you with a simple test to check your browser's support for EC6. There is this great article by Addy Yosmani about the standard as well. Also checkout (git?) this website to get a brief overview about where it's implemented right now.


Features

I've jabbered a lot, let's see some code. In each of the sections below, I have highlighted (I couldn't resist the temptation) some of the most important features to get you up and running with it.

Saying that this is a very condensed list is anything but obvious, and if you want a somewhat complete rundown, I suggest you visit this link.

Classes

Remember the times when we had to define a class, and we all got gooed up in the horrendous mess of code filled with prototypes, function() and whatnot? No more. ECMAScript 6 solves this with the sexy class construct. Just a word of warning, JavaScript does not support classes, it's still not an Object-Oriented language. EC6 is just making it easier for us to do things.

Let's take an example here: I'll define a very basic class Person with the attributes firstName, lastName, and a function getFullName.

Old Syntax
var Person = function( firstName, lastName ) {

    this.firstName = firstName || "John";
    this.lastName  = lastName  || "Doe";

};

Person.prototype.getFullName = function () {
    return this.firstName + " " + this.lastName;
};

Using this class is very straightforward:

var personOne = new Person( "Shreyansh", "Pandey" );
console.log( personOne.getFullName() );
New Syntax

Prepare yourselves to get your mind blown.

class Person {

    constructor( firstName, lastName ) {

        this.firstName = firstName;
        this.lastName  = lastName;

    }

    getFullName() {
        return `${ this.firstName } ${ this.lastName }`;      
    }

}

Usage still remains the same

var person = new Person( "Shreyansh", "Pandey" );
console.log( person.getFullName() ); 

Now, I know all of you are wondering what that ${} syntax means; the more perceptive of you must have guessed what it is; however, the next sections decribes it in detail.

Template Strings

People who come from a Python or a Ruby background, probably know what template strings are; for all those of you who don't, it's something pretty simple: you can embed expressions within strings. Thought of 100 use-cases? Cool, let's see.

Old Syntax
var a = 10
  , b = 20;

console.log( "The sum of a and b is: " + ( a + b ) );

// Some string formatting
console.log( "In 5 years, I will have " + ( b - a ) + " coins in my piggy-bank." ); 

Old, boring, and worst of all: confusing.

New Syntax
var a = 10
  , b = 20;

console.log( `The sum of an and is be: ${ a + b }` );

// String formatting? Bring it on!!
console.log( `In 5 years, I will have ${ b - a } coins in my piggy-bank.` );

To use string formatting, you wrap the entire string in `backticks` and to evaluate an expression, you wrap it in ${}.

const and let

Now, all of you who know a little bit about EC6 are probably cursing me that I didn't use the golden star of ECMAScript 6: the const and the let keywords. I know. (Duh.) These things are a little special and to use there here would be a waste.

let and const are block scoped. That's uber jargon for saying that their value depends on the scope, or the block where they're defined. Let me give you an example.

Old JavaScript
function someFunction() {

    var myVariable = 10;

    if( true ) {

        var myVariable = 20;
        console.log( "Value inside the block: " + myVariable );

    }

    console.log( "Value outside the block: " + myVariable );

}

someFunction();

In both the cases, the output will be 20. Why? Because EC5 treats both the variables as the same. There is no distinction; and because of this, you end up writing complex spaghetti. Not code. Try it out here.

To fix this, ES6 introduces let and const. Let's see let first.

function someFunction() {

    let myVariable = 10;

    if( true ) {

        let myVariable = 20;
        console.log( "Value inside the block: " + myVariable );

    }

    console.log( "Value outside the block: " + myVariable );

}

someFunction();

The console output will be: 20 and then 10. Cool, right?! We now have block-scoped variables. "Fiddle" around with this example here.

However, if you use the var keyword in either: ES5 or ES6, it'll behave exactly like var does: you won't get block-level scoping.

Arrow Functions

This is the best example of syntactic sugar.

Remember those terrible days when you had to write an entire declaration for an anonymous function; well, ES6 solves that with arrow functions.

The perfect example is when you're using the .map() method.

In VanillaJS, using this will be something like this

...
var a = b.map( function( element ) {

    return element * 2;

});

For something as simple as that, it's too much to write. Let's see if our lad ES6 has something to offer.

...
const a = b.map( element => element * 2 );

YEAH! That looks a lot better. These are arrow functions.

Another good thing about arrow thing is that it supports lexical binding for this.

What that essentially means that the keyword this will refer to the function enclosing the function rather than the function itself. An example is worth a thousand words, let's have a look.

Assume the following:

function Person() {

    this.age = 0;        

    setInterval( function() {

        this.age++;
        console.log( "My age now is " + this.age );

    }, 1000 );

}

var p = new Person();

According to the code above, you are older than the universe. Bravo! Caught the problem? No? Okay, it's actually pretty simple. Every anonymous function has its own this. Very simply put, whenever you define an anonymous function, the variable this gets attached to that function and not its container. Again, EC6 to the rescue.

Let me simplify the code:

function testItOut() {

    this.name = "Shreyansh";
  
    someFunc( function() {
  		
      	// Here, 'this' refers to the anonymous function for someFunc, and not
        // 'testItOut'. We solve this problem in ES6.
      
        // So, we can't refer to the property we defined above: 'name'. 
      
    });
  
}

Got it? Awesome! ES6's arrow functions solve this.

function Person() {

    this.age = 17; // because, why not!?        

    setInterval( () => {

        // Because of lexical binding, 'this' refers to the Person() function (class)
        // and not the enclosed function. Cool, right? 
                
        this.age++;
        console.log( "Now my age is " + this.age );

    }, 1000 );

}

var p = new Person();

Now you have an age. Good. Girls won't be happy, but yeah. Okay, that was a bad one, and a sexist one; I am sorry.

Modules and import

One of the best parts of EC6 is that it has module support baked into it. Defining and consuming modules is as easy as writing your first hello world program (not if you use Python.)

Let's have a look at some of the examples. :D

Defining a Module
...
module.exports = function() {
    return "Hello World";
}

And using it like:

...
var a    = require( './module' );

console.log( a() );

Not bad, huh? We can make it better. Let's see how ES6 "sexifies" it.

...
export default () => "Hello World";

Using this is a breeze.

...
import fooBar    from './module';

console.log( fooBar() );

Easy right? There's more.

Multiple Exports

So, many a times you have to export multiple things in a module. Say functions, constants, and what not. You won't believe how easy it is with ES6.

First, let's see how it's done with VanillaJS.

... 
var pi  = ( 22 / 7 )
  , tau = 2 * pi;

var area = function( r ) {
    return ( pi * Math.pow( r, 2 ) );
}

module.exports = {

    pi     : pi,  
    tau    : tau,

    getArea : area

};

Consuming it is a little jammed up

var MathClass =    require( './module' );
...

console.log( MathClass.getArea( 100 ) );

Works? Yes. Pretty? Nope.

Let's clean it up with our beloved ES6.

...
const pi  = ( 22 / 7 )
    , tau = ( 2 * pi );

const area = r => {

    return ( pi * Math.pow( r, 2 ) );

};

export {

    pi,
    tau,
    area        

};

To use this, there are a couple of ways.

import * as MathClass from    './module';

console.log( MathClass.area( 20 ) );

Or if you want to import just one specific function:

...
import {
   area
} from './module';

console.log( area( 20 ) );

Easy, right? Yep.

I guess that wraps it up for this post.


Conclusion

Well, that's it for this one. I hope you learnt something. And, if there was any problem in understanding anything, don't hesitate in messaging me or mailing me.

I seriously hope that you liked this post; in future posts, we'll see how you can use ES6 in your next firey project. So, stay tuned! :)