Seleccionar página

Introduction to ECMAScript 6 (ES6)

As you probably already know, ECAMScript is the name of the international standard that defines JavaScript. ECMAScript 6 (also known as ECMASCript 2015 and ES6) is the latest version and was approbed more than one year ago. In this tutorial of ECMAScript 6 (ES6) you will find everything you need to get started with ECMAScript 6.

Introduction to ECMAScript 6

You need to know that ES6 is not still widely supported by all browsers, which means that transpilation to ES5 is needed through one of the currently available transpilers on the JavaScript world (Babel, CoffeScript, …) to ensure that our could will be correctly executed. If you feel curious about the compatibility of the features described in this post, you can visit the ES6 Compatibility Table.

Some of the most important features that ES6 has introduced are:

  • Classes and inheritance
  • Arrow functions
  • Template Strings
  • Block variables: ley keyword
  • Const variables
  • Shorthand object literals

Let’s talk about them and introduce some of the new features.

Block variables

Like other programming languages such as Java or PHP, ES6 considers the block scope for variables. This means that now we can choose between the previous function scope (used in ES5, var keyword) and the new block scope. The way of declaring block scope variables will be using the keyword let.

 

var x = 5;
var test = true;
if(test) {
    var y = x
    let z = x;
}
console.log(y); //5 
console.log(z); //undefined 

Const variables

There is now support for constant (inmutable) variables. Using the const keyword we will ensure that the defined variable cannot be reasigned with other content.

 const PI = 3.141593 

Arrow functions

Arrow functions is the name for the new sintax introduced by ES6 in order to define functions in an easy way.

The syntax:

() => { ... } // no parameter
x => { ... } // one parameter, an identifier
(x, y) => { ... } // several parameters

x => { return x + 1 }  // block body, return is needed to give back a value. 
x => x + 1  // single expression, braces not needed. The expression is always implicitly returned.

Comparison between code with and without arrow functions:

//ES5
function(x) {
	return x++;
}

//ES6
(x) => x++; //Remember, braces are not needed for single expressions.

//ES5
function(str= {
	console.log(str);
	return str.toLowerCase();
}

//ES6
(str) => {
	console.log(str);
	return str.toLowerCase();
}

It is important to mention other big difference when using arrow functions: this keyword referes to the outer scope and not to a local copy of this.


//ES5
var self = this;
this.nums.forEach(function (v) {
    if (v % 5 === 0)
        self.fives.push(v);
});

//ES6
this.nums.forEach((v) => {
    if (v % 5 === 0)
        this.fives.push(v)
})

Classes and inheritance

It could sound unvelibable, but you have read it correctly, classes are one of the new features in ES6.


class Person {
	
	constructor(name, age){
		this.name = name;
		this.age = age;
	}

	walk(){
		//method code
	}
}

class Student extends Person {
	
	constructor(name, age, course){
		super(name,age);
		this.course = course;
	}

	study(lesson){
		//method code
	}	

Before in ES5:


var Person = function (name, age) {
    this.name = name;
    this.age = age;
};
Person.prototype.walk= function () {
    //method code
};

var Student = function (name, age, course) {
    Person.call(this, name, age);
    this.course = course;
};

How can we create an instance of a class? Class objets are created using the new operator:

let myPerson = new Person();

It is important to mention that unlike Java classes, the reserved word this refers to the calling context and not strictly the object itself (it will refere to the object when accessing a member or method of the instances using the dot notation).

Base class access using super


//ES6
class Shape {
    …
    toString () {
        return `Shape(${this.id})`
    }
}
class Rectangle extends Shape {
    constructor (id, x, y, width, height) {
        super(id, x, y)
        …
    }
    toString () {
        return "Rectangle > " + super.toString()
    }
}

//ES5
var Shape = function (id, x, y) {
    …
};
Shape.prototype.toString = function (x, y) {
    return "Shape(" + this.id + ")"
};
var Rectangle = function (id, x, y, width, height) {
    Shape.call(this, id, x, y);
    …
};
Rectangle.prototype.toString = function () {
    return "Rectangle > " + Shape.prototype.toString.call(this);
};

Static Members


class Rectangle extends Shape {
    …
    static defaultRectangle () {
        return new Rectangle("default", 0, 0, 100, 100)
    }
}
class Circle extends Shape {
    …
    static defaultCircle () {
        return new Circle("default", 0, 0, 100)
    }
}
var defRectangle = Rectangle.defaultRectangle()
var defCircle    = Circle.defaultCircle()

Like traditional Java language classes, they can implement interfaces and contain both static and instance members and methods. Some of the differences with traditional classes (apart from the syntax) are the possibility to include optional parameters and the restriction of having a unique constructor.

Template strings

In ES6 there is a new way of defining strings apart from the use of “ or ‘. Enclosing the text withing back ticks will be the new way for creating string literals that can also be multi-line:


const firstName = 'Mike';
console.log(`Hello ${firstName}!
How are you
today?`);

// Output:
// Hello Mike!
// How are you
// today?

In case of using back ticks for defining a string variable, it will be possible to include interpolated expressions (inserted via ${···}):


var customer = { name: "Foo" }
var card = { amount: 7, product: "Bar", unitprice: 42 }
var message = `Hello ${customer.name},
want to buy ${card.amount} ${card.product} for
a total of ${card.amount * card.unitprice} bucks?` 

var customer = { name: "Foo" };
var card = { amount: 7, product: "Bar", unitprice: 42 };
var message = "Hello " + customer.name + ",\n" +
"want to buy " + card.amount + " " + card.product + " for\n" +
"a total of " + (card.amount * card.unitprice) + " bucks?";

Line terminators in template literals

Line terminators are normalized to LF (\n) in template literals. That is, the following code logs true on all platforms:


const str = `HELLO
BYE`;
console.log(str === 'HELLO\nBYE'); // true

Default parameter values

Default parameter values can be defined in functions:

function f(x, y=0) {
  return [x, y];
}

//We can complicate more:
function foo(x=3, y=x) {}
foo();     // x=3; y=3
foo(7);    // x=7; y=7
foo(7, 2); // x=7; y=2

Rest parameters

We can now aggregate remaining arguments of a function into a single parameter. This arguments will be grouped in an array:

function f (x, y, ...a) {
    return (x + y) * a.length
}
f(1, 2, "hello", true, 7) === 9

Modules

ECMAScript 6 comes with support for importing and exporting values from module. The modules are stored in files and there is one module per file and one file per module. Some important aspects of ES6 modules are:

  • ECMAScript 6 modules don’t pollute the global namespace (they avoid global variables).
  • They load asynchronously.
  • The declarations remain local (only the ones marked with ‘export’ can be imported).
  • There is only one instance per module, even thought it has been imported several times.

The following code example show us how to export and import a module.


//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5

Example importing the complete module:

//------ main.js ------
import * as lib from 'lib';
console.log(lib.square(11)); // 121
console.log(lib.diag(4, 3)); // 5

Exporting a single class or function

There is also the possibility to export & import a single function or class


//------ myFunc.js ------
export default function () { ··· } // no semicolon!

//------ main1.js ------
import myFunc from 'myFunc';
myFunc();

//You can do the same with a class:

//------ MyClass.js ------
export default class { ··· } // no semicolon!

//------ main2.js ------
import MyClass from 'MyClass';
const inst = new MyClass();

If you liked the article and want to learn more about ES6

You can visit the sources used for the article: