javascript

ES6 Features

This essay will give you a quick introduction to ES6. If you don’t know what is ES6, it’s a new JavaScript implementation.

ES6 has mostly syntactic sugar. 


Default Parameters in ES6

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

 var link = function (height, color, url) {
        var height = height || 50;
        var color = color || 'red';
        var url = url || 'http://azat.co';
 }

In ES6, we can put the default values right in the signature of the functions:

var link = function(height = 50, color = 'red', url = 'http://azat.co') {
  ...
}

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:

var name = 'Your name is ' + first + ' ' + last + '.'
var url = 'http://localhost:3000/api/messages/' + id

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

var name = `Your name is ${first} ${last}.`
var url = `http://localhost:3000/api/messages/${id}`

Arrow Functions in ES6

CMAScript 6 facilitates how we write anonymous functions, as we can completely omit the function keyword. We only need to use the new syntax for arrow functions, named after the => arrow sign (fat arrow), that provides us with a great shortcut.

// 1. One parameter in ES6
let sum = (a, b) => a + b;
 
 // in ES5
 var sum = function(a, b) {
 return a + b; 
 };
 
// 2. Without parameters in ES6
let randomNum = () => Math.random();
 
 // in ES5
 var randomNum = function() {
 return Math.random(); 
 };
 
// 3. Without return in ES6
let message = (name) => alert("Hi " + name + "!"); 
 
 // in ES5
 var message = function(yourName) {
 alert("Hi " + yourName + "!"); 
 };

There’s an important difference between regular and arrow functions, that is arrow functions don’t receive a this value automatically like functions defined with the function keyword do. Arrow functions lexically bind the this value to the current scope. This means that we can easily reuse the this keyword in an inner function. In ES5 it is only possible with the following hack:

// ES5 Hack to use the "this" keyword in an inner function
{
 ...
 addAll: function addAll(pieces) {
 var self = this;
 _.each(pieces, function (piece) {
 self.add(piece);
 });
 },
 ...
}
 
// ES6 the same inner function now can use its own "this"
{
 ...
 addAll: function addAll(pieces) {
 _.each(pieces, piece => this.add(piece));
 },
 ...
}

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():

setTimeout(function(){
  console.log('Yay!')
}, 1000)

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

var wait1000 =  new Promise(function(resolve, reject) {
  setTimeout(resolve, 1000)
}).then(function() {
  console.log('Yay!')
})

Block-Scoped Constructs Let and Const

ES6 introduces the new let keyword that allows us to declare local variables in the scope of a block, such as a statement, an expression, or a(n inner) function. For example we can declare a for loop in the following way, then reuse the same variable name (as its scope is limited to the for loop) inside the next ifstatement:

for (let i = 0; i < myArray.length; i++) { 
 // Do something inside the block 
}
 
if (x > 0 && x != y) {
 // We reuse "i"
 let i = x * y
}

Using the let keyword leads to a cleaner and more usable code. The difference between let and var is in the scope, for example a local variable defined by the var keyword can be used in the entire enclosing function, while variables defined by let only work in their own (sub)block. Let can also be used globally, in this case it behaves the same way as var. Of course, in ES6 we can still use var if we want.


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:

class baseModel {
  constructor(options = {}, data = []) { // class constructor
        this.name = 'Base'
    this.url = 'http://azat.co/api'
        this.data = data
    this.options = options
    }

    getName() { // class method
        console.log(`Class name: ${this.name}`)
    }
}

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:

class AccountModel extends baseModel {
    constructor(options, data) {

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

    super({private: true}, ['32113123123', '524214691']) 
    //call the parent method with super
        this.name = 'Account Model'
        this.url +='/accounts/'
    }

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

    get accountsData() { //calculated attribute getter
    // ... make XHR
        return this.data
    }
}

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

let accounts = new AccountModel(5)
accounts.getName()
console.log('Data is %s', accounts.accountsData)

In case you’re wondering, the output is:

Class name: Account Model
Data is %s 32113123123,524214691

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.

Let’s say we have portvariable and getAccounts method in ES5 module.js:

module.exports = {
  port: 3000,
  getAccounts: function() {
    ...
  }
}

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

var service = require('module.js')
console.log(service.port) // 3000

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

export var port = 3000
export function getAccounts(url) {
  ...
}

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

import {port, getAccounts} from 'module'
console.log(port) // 3000

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

import * as service from 'module'
console.log(service.port) // 3000

New const Keyword

The new const keyword makes it possible to declare constants, also known as immutable variables, to which we cannot reassign new content later.

const MY_CONST = 12;
console.log(MY_CONST);
// 12
 
MY_CONST = 16;
// Silent error, as we cannot reassign a new value to a constant

Immutable variables are not always fully immutable in ECMAScript 6 though, as if a constant holds an object, we can later change the value of its properties and methods. The same is true for the elements of an array.

const MY_CONSTANT = {myProperty: 6};
console.log(MY_CONSTANT.myProperty);
// 6

MY_CONSTANT.myProperty = 18;
console.log(MY_CONSTANT.myProperty);
// 18

const OTHER_CONSTANT = [12, 14, 16];
console.log(OTHER_CONSTANT[0]);
// 12

OTHER_CONSTANT[0] = 22;
console.log(OTHER_CONSTANT[0]);
// 22

New spread Operator

The new spread operator is marked with 3 dots (…), and we can use it to sign the place of multiple expected items. One of the most common use cases of the spread operator is inserting the elements of an array into another array:

let myArray = [1, 2, 3];
let newArray = [...myArray, 4, 5, 6];
console.log(newArray);
// 1, 2, 3, 4, 5, 6

We can also take leverage of the spread operator in function calls in which we want to pass in arguments from an array:

let myArray = [1, 2, 3];

function sum(a, b, c) {
 return a + b + c;
}
console.log(sum(...myArray));
// 6

The spread operator is quite flexible, as it can be used multiple times in the same array or function call.


New for...of Statement

With the help of the new for...of loop we can iterate over arrays or other iterable objects easily. Along with the new for...of statement, ECMAScript 6 introduces two new iterable objects too, Map for key/value maps, and Set for collections of unique values that can also be primitive values and object references. When we use the for...of statement, the code inside the block is executed for each element of the iterable object.

let myArray = [1, 2, 3, 4, 5];
let sum = 0;
 
for (let i of myArray) {
 sum += i;
}

console.log(sum);
// 15 (= 1 + 2 + 3 + 4 + 5)

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s