Introduction to ECMA Script 6 - New features with examples

Wed Sep 30 2015

Paul Shan

When JavaScript was first created, probably the motto was to manipulate the DOM, form submission etc. But slowly and gradually this little web script has grown like a giant. Today JavaScript is being used in browsers, devices, servers and even as database query language. It’s being used for much much more than it’s ever conceived for. ECMA Script harmony or ES6 came up with some significant changes and feature-set to make JavaScript better for those. Below are the descriptions of most of the newly added features with example. And to try, test and play with ES6 code there are various ways available. ** You can try and test ES6 code in various ES6 playgrounds

The great dot dot dot (rest or spread) operator

I personally find this feature the most interesting one. I’m mentioning it at the very beginning, cause in many examples below you will find me using this …rest feature. For the time being you just think this as an object/array that holds the rest of the values after some initial variable declaration. This feature can be very much useful where you expect a function to accept undefined number of parameters after a certain set of fixed parameters. For better understanding you can imagine the printf function of C language.

Variable declaration

ES6 has emphasized on block scopping. As most of the language uses block scope and not function scope, which JavaScript does use; ES6 decided to introduce two new keywords “let” and “const”. A brief on let, var and const of ES6 in already covered before on Void Canvas, so here I’m just giving the bulet points.
  • Unlike var; let and const are block scopped.
  • let and const variables have temporal dead zones.
  • You can not declare the same variable twice in the same scope. In case of var it doesn’t matter, but let and const will throw error.
  • If a let or const variable is in global scope, unlike var it will not become a property of the global object (window in case of browsers and global in case of node.js)
  • New destructuring feature of objects and arrays are also introduced.
  • To know more about variable declarations you can check our article on ES6 variable declaration.

Example of dot dot dot (rest)

Considering you have gone through our variable declaration article I’m providing the example below for an understanding of …rest.
function func (argument) {
    let arr = [ 'a', 'b', 'c', 'd','e','f','g' ];
    let [x, y, ...rest] = arr;
    console.log('rest is:  ' + rest); // c,d,e,f,g
}

Functions have tremendous enhancements

There are quite a few new functionalities for function parameter handling; i.e. default values, named parameters, arrow functions, lexical this etc. A brief is as below.

Default parameter values

From ES6 implementation in JavaScript, you will be able to provide default values while defining the function. Below is an example.
function func (a, b=2, c=3) {
  console.log("a is "+a+"\n"); //a is 100
  console.log("b is "+b+"\n"); //b is 200
  console.log("c is "+c+"\n"); //c is 3
}
func(100,200);

Named parameters

Though you have did this with ES5 too; by setting an object as a parameter and accessing the required properties via that object. But ES6 not only removes a “someObject.” but also gave you a more comprehensive and proper way with less memory consumption. Have a look.
function func (param1,{firstName,lastName}) {
  console.log("param1 is "+param1+"\n"); // param1 is 100
  console.log("name is "+firstName+ " "+lastName+"\n"); //name is Paul Shan
}

func(100,{firstName:"Paul", lastName:"Shan"});

Arrow functions

Arrow function is another stylish feature of ECMA Script 6. This is a way to define a function in just a single line; separating the input and output with an => arrow sign.
//Eg:1
let p =10;
console.log("p X p = "+(p=>p*p)(p)); //p X p = 100

//Eg:2
let squares = [1, 2, 3].map(x=>x*x);
console.log(squares); // [1,4,9]

//Eg:3
setTimeout(()=>{
  console.log("Example by Void Canvas"); //Example by Void Canvas
},100);

Lexical this

The this keyword has a significant change. Now this will work exactly like the this in strongly typed language. But as ES6 promised you to give 100% backward compatibility, it didn’t change the “this” in normal functions, but only in arrow functions.
//Example 1 : with normal function
var obj={
  successFunc:function () {
    console.log("Success");
  },

  testFunc:function () {
    setTimeout(function () {
      if(this.successFunc)
        this.successFunc();
      else
        console.log("Failure");
    },100);
  }
}
obj.testFunc(); //Failure will be printed

//Example 2 : with arrow function
var obj={
  successFunc:function () {
    console.log("Success");
  },

  testFunc:function () {
    setTimeout(() => {
      if(this.successFunc)
        this.successFunc();
      else
        console.log("Failure");
    },100);
  }
}
obj.testFunc(); //Success will be printed
In Example 1, the “this” was not referring to the obj object; rather it was pointing to the current execution context; which is the normal behavior of ES5. But in ES6 if you use “this” keyword inside the arrow function, it will point to the parent object only; which is a normal behavior in Java, C# etc. This will actually omit the need of that=this; kind of code.

Dot dot dot inside function

Let’s see how our beloved dot dot dot works as a function parameters.
function printf (str, ...others) {
  var finalString = str;
  if(others){
    others.forEach(function (val) {
      finalString=finalString.replace("%s",val);
    });
  }
  console.log(finalString);
}
printf("first name is %s and last name is %s","Paul","Shan"); //first name is Paul and last name is Shan

Another beauty of dot dot dot

If you have an array and want to pass each element as a function parameter, your spread operator dot dot dot will help you again. Below is an example.
function func (a, b, c) {
  console.log("a is "+a+"\n"); //a is 100
  console.log("b is "+b+"\n"); //b is 200
  console.log("c is "+c+"\n"); //c is 300
}

var arr = [100,200,300];

func(...arr);

Class and new Object orientations

Yes, it was very much possible to create classes (constructors to be very specific) in ECMA Script Vanilla; but that was certainly not the best approach. It was too complicated too. ES6 came up with a proper approach of classes which will make inheritance and other OOP related operation very much like strongly typed languages. Below are the examples.

Basic class

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

    who() {
        return this.name + " is " + this.age + "years old.";
    }
}
let breddy = new Human("Breddy",24);
console.log(breddy.who()); //Breddy is 24years old.
console.log(breddy instanceof Human); //true

Inheritance

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

    who() {
        return this.name + " is " + this.age + "years old.";
    }
}

class Student extends Human {
    constructor(name, age, school) {
        super(name, age);
        this.school = school;
    }
    who() {
        return super.who() + ' He goes to ' + this.school + " school.";
    }
}

let breddy = new Student("Breddy",24,"Havard");
console.log(breddy.who()); //Breddy is 24years old. He goes to Havard school.
console.log(breddy instanceof Student); //true
As you can see, stuffs are very easy to write and also to understand. The best thing is you can directly call the “super”. No need to call the super by it’s name.

Support to inherit built in classes

You can extend the inbuilt classes of JavaScript too (eg: Object, Error, Array etc).
class MyError extends Error {
  // do your stuff
}
throw new MyError('An error occured!');

getters and setters

They work pretty much like ES5.
class MyClass {
    get prop() {
        return 'getter';
    }
    set prop(value) {
        console.log('setter: '+ value);
    }
}

let inst = new MyClass();
inst.prop = 123; //setter: 123
console.log(inst.prop) //getter

Static method

class MyClass {e
    constructor(prop) {
        this.prop = prop;
    }
    static staticMethod() {
        return 'I am static';
    }
    prototypeMethod() {
        return 'I am NOT Static';
    }
}
let inst = new Myclass(123);
console.log(inst.prototypeMethod()); //I am NOT Static
console.log(MyClass.staticMethod()); //I am static
console.log(MyClass.prototypeMethod()); //Error: prototypeMethod is not a function
console.log(MyClass.prototype.prototypeMethod()); //I am NOT Static
The non static members can also be called using the class’s prototype.

Similarity / difference with ES5

  • If you check typeof your class, you will find it’s “Function”. Just like ES5 constructor.
  • But you can’t call the class a function. It will throw error.
  • ClassName.prototype is non-writeable, non-enumerable, non-configurable; however ClassName.prototype.* are writable and configurable, but not enumerable.
  • Hoisting is not allowed for classes. In ES5 classes it was allowed, but ES6 has temporal dead zone for classes.

ES6 classes provide a few clear benefits:

  • Best for the people who worked with other strongly typed languages.
  • Inheritance is very easy and requires less lines of code.
  • For the first time, we will be able to use “super” keyword to refer the base class directly.
  • Built in constructors.
  • This is a foundation for mixins too.
  • JS IDEs will become more intelligent now.
  • They are backwards compatible with much of the current code.

Modules in ES6

Moduling is pretty necessary these days in JavaScript as the apps are getting very big and complicated. IN todays JavaScript world two moduling techniques are very popular. One is CommonJS (node.js style) and another is Asynchronous Module Definition; (require.js style). In ES6, modules are very similar to both of these techniques. Below are some examples.

Basic overview

//defining modules

//------ math.js ------
export function add(a,b) {
    return a+b;
}
export function subtract(a,b) {
    return a-b;
}

//------ main.js ------
import { add, subtract } from 'math';
console.log(add(11,2)); // 13
console.log(subtract(4, 3)); // 1

//------ main2.js --------
import * as math from 'math';
console.log(math.add(11,2)); // 13
console.log(math.subtract(4, 3)); // 1

You can export the methods and properties from a file, which will be considered as modules. In some other file you can selectively (or all) import them. In main.js I specifically imported only two functions of math.js; whereas main2.js imported all the functions with a namespace. The same thing can be done in CommonJS style too. Below is the example.
function add(a, b) {
    return a+b;
}
function subtract(a, b) {
    return a-b;
}
module.exports = {
    add: add,
    subtract: subtract
};

//------ main.js ------
var add = require('math').add;
var subtract = require('math').subtract;
console.log(add(11,2)); // 13
console.log(subtract(4, 3)); // 1

//---- main2.js -----
var math = require('math');
console.log(math.add(11,2)); // 13
console.log(math.subtract(4, 3)); // 1

default export

Now what I want is to export only a single function or a property, or may be a class without any separate name. The new default keyword helps you to do that. Below is an example.
//------ Human.js ------
export default class {
    constructor(name){
        this.name=name;
    }
}

//------ main2.js ------
import Human from 'Human';
let me = new Human("Paul");

Few more features of modules

  • Rename imports
  • Module IDs are configurable (default: paths relative to importing file)
  • Programmatic (e.g. conditional) loading of modules via an API
  • Module loading is configurable

Template in ES6

This is again another great feature in ES2015. You may have used template engines like handlebars, jade etc and have tasted the easiness of coding with these. ES6 is coming with it’s native template engine, using which not only you can template your code, but the giant template engines like handlebars can become more powerful and faster. Below are few examples of templating in ES6.

Simple template

Previously it was single quote and double quote; now ES6 has come up with back quote. The template string much be in between two back quotes. Below is a simple example
let firstName = "Paul";
let lastName = "Shan";

console.log(`full name is ${firstName} ${lastName}`); //full name is Paul Shan

Operations inside curly braces

You can perform normal operations inside that dollar curly braces.
let firstName = "Paul";
let lastName = "Shan";

console.log(`full name is ${firstName} ${lastName}. Age is ${10+10+6}`); //full name is Paul Shan. Age is 26

No ugly multi-line string

Upto ES5, it’s really a problem to declare a long string with multi lines. You either have to use escape characters, or have to concat each lines separately. But in ES6 with back quotes you can easily declare a multi line string (an actual multi line string) with no ugliness.
//In ES5
var str = "Hi all \
I am Paul \
showing you JS examples";
console.log(str); //Hi all I am Paul showing you JS examples

var str2 = "Hi all "+
"I am Paul "+
"showing you JS examples";
console.log(str); //Hi all I am Paul showing you JS examples

//In ES6
let str3 = `Hi all
I am Paul
showing you JS examples`;
console.log(str3);
//Hi all
//I am Paul
//showing you JS examples

Template helpers

With template helpers the parameters are little weird. If you have a single parameter as string (if dollar curly braces are not used for params), it will be passed to the helper functions as the first param. But if you send value parameter to the helper (using dollar curly braces), you will be able to send multiple parameters and will find this from argument[1].
//Eg 1: pass a single string
function getLength(str){
  return str[0].length;
}
console.log(`length of VoidCanvas is ${getLength `VoidCanvas`}`)

//Eg 2: passing multiple value
let firstName = "Paul";
let lastName = "Shan";

function fullName(stringKey, value1, value2){
  return value1 + " " + value2;
}

console.log(`full name is ${fullName `${firstName} ${lastName}`}`); //full name is Paul Shan

A complicated one

I’ve already discussed about arrow functions and also about my favorite dot dot dot operator. The example below contains both of these two and of course the templates.
//iterate on an array and print all values
let templateStr = nameList => displayName`
  Names are as follows:
  ${nameList.map(name => displayName`
    ${name.first} ${name.last}`
  )}
`;
console.log(templateStr([
  {first:"Paul", last:"Shan"},
  {first:"Lois", last:"Lane"}
]));

function displayName(literalSections, ...values){
  let output = "";

  output += recursiveArrayJoin(literalSections);
  output += recursiveArrayJoin(values);

  return output;
}

function recursiveArrayJoin(arr){
  let output = "";
  arr.forEach(element => {
    if(element.trim){
      if(element.trim())
        output+=element+ " "
    }
    else{
      if(element && element.length)
        output += recursiveArrayJoin(element);
    }
  });
  return output;
}

Loops - iterators - generators in ES6

ES6 has introduced a new “for-of” loop, which is capable of iterate through an array or a string (not object). Though it looks pretty similar to “for-in” loop, but it isn’t. New “for-of” loops iterates on values, whereas “for-in” used to do it with property name. The example below will clarify this.

for-of loop example

var myArr=["Void", "Canvas"];

var myStr = "voidcanvas.com";

var myObj={
 "firstName":"Paul",
 "lastName":"Shan"
};

for(var i in myArr){
 console.log(i); // 0 1
}
for(var v of myArr){
 console.log(v); // Void Canvas
}

for(var i in myStr){
 console.log(i); //0 1 2 3 4 5 6 7 8 9 10 11 12 13
}
for(var v of myStr){
 console.log(v); //voidcanvas.com
}

for(var i in myObj){
 console.log(i); //firstName lastName
}

//ERROR: not a function.
for(var v of myObj){ // Because for of is not applicable in objects
 console.log(v);
}

Generators

Generators in ES6 are awesome. Why awesome? Let me describe with an example. Suppose, you are iterating an infinite loop (though it’s bad programming, but just assume the situation). And there are some other tasks who is waiting to be executed. But as JavaScript is single threaded, that task will never run, because the thread was busy and there was no stop or pause.
//problem
setTimeout(function(){
    console.log("interruption!");
},100);
while(true){
    console.log("hello!");
}
Even if the while loop is not infinite and iterates 10000 times, than also the setTimeout() won’t be able to execute the function to print “interruption”. But generators can be paused or interrupted while looping. Interruptions are allowed in these because generators uses yield inside it. Below is an example code of generator.
function* iteratorGenerator(arr){
  for(var i=0;i

To know more about ES6 generators you can refer David Walsh’s blog post.

Symbol

Something like Enum has been introduced to JavaScript now. This is called Symbol. This is a new type of primitive value. Let's see how Symbol actually works.

Overview

var sym = Symbol();
var foo = Symbol("foo");
typeof sym;     // "symbol"

var symObj = new Symbol(); // TypeError
var symObj = Object(sym);
typeof symObj;  // "object"

Symbol("foo") === Symbol("foo"); // false

Usage

//previously
var red = "red";
var green = "green";
var blue = "blue";

function handleColor(color) {
  switch(color) {
    case "red":
    //do your stuff

    case "green":
    //do your stuff

    case "blue":
    //do your stuff
  }
}

//with Symbol
const red = Symbol();
const green = Symbol();
const blue = Symbol();

function handleColor(color) {
  switch(color) {
    case red:
    //do your stuff

    case green:
    //do your stuff

    case blue:
    //do your stuff

  }
}

Important methods

The two important methods are Symbol.key() and Symbol.keyFor()
let foo1 = Symbol.for("foo"); // create a new  symbol
let foo2 = Symbol.for("foo"); // retrieve the already created symbol

foo1 === foo2 // true

Symbol("bar") === Symbol("bar"); // false

var globalSym = Symbol.for("foo"); // create a new global symbol
Symbol.keyFor(globalSym); // "foo"

Few more on ES6 Objects

Let’s check some other new methods and libraries in ES6 with small examples.

Map

let map = new Map();
let obj = {a:1};
let func = function(){
    var a=1;
}
map.set(obj, 123);
map.set(func, "This is fun");
console.log(map.size); // 2
console.log(map.get(obj)); // 123
console.log(obj); // {"a":1}
console.log(map.get(func)); // This is fun
console.log(map.has(obj)); // true
map.delete(obj);
console.log(map.has(obj)); // false
Map is nothing but a key value pair; just like the JavaScript objects. But there are few differences. They are as below:
  • The property key of an object can only be string. Whereas the key of a Map can be string, Object, Function or anything.
  • If you iterate on a Map, it will iterate exactly in the same order the values were pushed, whereas in case of objects this is not followed.
  • Using map.size you can easily get the size of it. But in case of Objects you need to find the size manually.

Set

let set1 = new Set();
set1.add('hello');
set1.add('hello');
console.log(set1.has('hello')); // true
console.log(set1.has('world')); // false
let set2 = new Set([3,2,1,3,2,3]);
console.log(set2.size); //3
console.log(set2.values()); // {3,2,1} - it returns unique values in insertion order
console.log(set2.entries()); // {[3,3],[2,2],[1,1]} - it returns all the values inserted
Set is an Object to store unique primitive as well as object references. However it doesn’t throw error if you want to add a duplicate value, but silently make the set unique.

Object.assign()

Now it’s easy to extend or combine two objects with Object.assign(). Below is an example.
var one = {a:1};
var two = {b:2};
Object.assign(one,two);
console.log(one); // {"a":1,"b":2}
console.log(two); // {"b":2}

More on ES6 String

The methods below belongs to the String.prototype. I mentioned the headings as String.method() for better understanding. Examples describes the usage.

String.repeat(int)

'abc'.repeat(3); // abcabcabc
'abc'.repeat(3.6); // abcabcabc
'abc'.repeat("2"); // abcabc
'abc'.repeat(-1); //range error

String.startsWith(string)

'abc'.startsWith('ab'); // true
'123'.startsWith(1); // true
'abc'.startsWith('b'); // false

String.endsWith(string)

'abc'.endsWith('bc'); // true
'123'.endsWith(3); // true
'abc'.endsWith('b'); // false

String.contains(string)

'abc'.contains('bc'); // true
'123'.contains(3); // true
'abc'.contains('x'); // false

More on ES6 Array

The methods below belongs to the Array.prototype. I mentioned the headings as Array.method() for better understanding. Examples describes the usage.

Array.find(arrow=>function)

It finds the first element and stops there.
var a=[13,7,8,22].find(x => x % 2 === 0)
console.log(a); //8

Array.findIndex(arrow=>function)

It finds the index of the first occurrence
var a=[13,7,8,22].findIndex(x => x % 2 === 0)
console.log(a); //2

SHARE THIS ARTICLE

post-thumbnail
Today everyone knows the importance of a lightning-fast website and how the speed impacts the conversion rate of a business. Today, everyone wants the site to be a PWA so that the mobile users can have an app-like experience with the website because, for the majority of the merchants, the customers come through mobile devices.
Tue Apr 20 2021
post-thumbnail
Here we are going to see how you can manage backup and restore of Postgres database with docker.
Thu Sep 03 2020
post-thumbnail
Image sliders or carousels always have increased the UI attraction of websites and they are pretty useful for reflecting the major roles/products too. In case, I am having a website that sells tee-shirts,
Mon Apr 30 2018

About VoidCanvas

This blog was created out of hobby and talks mostly about technology, web development, JavaScript, NodeJS and related topics. Thank you for reading my blog.

Copyright 2022 - www.voidcanvas.com

Popular Articles

Authentication using Google's oAuth api with node.js

Thu Mar 10 2016

OAuth authentications are pretty popular now a days and another thing which is popular is JavaScript. This article shows how to plugin google’s oAuth api for authentication in your own node application.

CSS3 Loader Snippet Collection: (Part 2 - Squares)

Sat Mar 01 2014

This is a continuation of my CSS3 loader snippet collection series. I've provided spinning css3 animation loader in the part 1 of this series and here in part 2, I'm providing various square type loading