Coders Read

ECMAScript (ES6, ES7, ES8) Features – Javascript

In this article, we will cover on how to utilize some of the features of the JavaScript ES6, ES7 and ES8 have to offer.

ES6 Features

1. Default Parameters

Before ES6 default parameters, we use to implement default parameters something like this –

function getCarDetail (year, model) {
    year = year || 2018;
    model = model || 'Sedan';
    // function body...
}

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.

In ES6, we can put the default values right in the signature of the function. i.e

function getInfo (year = 2018, model = 'Sedan') {
    // function body here...
}

More readable with less codes.

2. Arrow Functions

This is probably one of the most commonly used feature of ES5 which will be used by the developers on daily basis and is the most common question for frontend interviews.

Arrows is a new way to write functions, which brings several benefits. They would make your this behave properly — it won’t mutate. It automatically binds this to the surrounding code’s context. The syntax allows an implicit return when there is no body block, this results in simpler code.

let obj = {
  myVar: 'foo',
  
  myFunc: function() { 
    let self = this;    
    console.log(this.myVar)  
  
    setTimeout(function() {
      console.log(self.myVar)
    }, 1000)
  }
}

obj.myFunc()

This is the ES6 code

let obj = {
  myVar: 'foo',
  
  myFunc: function() { 
    console.log(this.myVar)  
  
    setTimeout(() => {
      console.log(this.myVar)
    }, 1000)
  }
}

obj.myFunc()

Let’s see another example to see what happens if we try to use an arrow function as an object method.

let obj = {
  myVar: 'foo',
  
  myFunc: () => { 
    console.log(this.myVar)  
  }
}

obj.myFunc()

Did you expect this to refer to obj.?

But arrow functions don’t bind this to the object that called them. In such case, this refers in the scope in which they were defined, here it is the global object. So arrow functions are unusable for object methods!

3. Let and Const — Block-Scoped

let and const are new variable declaration mechanisms introduced in ES6. It is the new variable declaration mechanism that respects scopes and doesn’t do hoisting the way var does.

let’s look at the some sample code to see how ‘let’ works…

SAMPLE 1
let version = ES5;
if (true) {
  let version = ES6;
  console.log(version); // ES6(inside block)
}
console.log(version) // ES5 (outside block)
SAMPLE 2
try{
  id = 010;
  console.log(id);
  let id = 101;
} catch(e) {
 console.log(e.message)
}

Output: // Cannot access 'a' before initialization
SAMPLE 3
let sum;
let sum; // ERROR

const does not allows reassignment of variables. It’s a static check. let’s look at the some sample code to see how ‘const’ works…

SAMPLE 1
const obj1 = {};
const obj2 = {};
obj2.val = 'Javascript';
console.log(JSON.stringify(obj2)); // {"val":"Javascript"}
o1 = o2; // // Error
SAMPLE 2
const x = 0;
x = x + 1; // Error

4. Classes

It makes writing classes and inheriting from them as easy. Being a front end developer, you might be aware that Javascript follows prototypal inheritance which sometimes can get a little confusing. With ES6 classes the syntax are much simpler.

ES6 Classes is the javascript pattern of getting the class like inheritance hierarchies with the help of prototypes and functions. JavaScript supports the Object-Oriented programming components.

  • Object: The presentation of any entity in real-time.
  • Class: Blueprint or a set of instructions to build a specific type of object
  • Methods: It communicates between the objects.
class Employee {
   constructor(emp) {
      this.empName = emp;
   }
}

class Developer extends Employee {
   showDetail() {
      console.log("Name of Employee:  "+this.empName)
   }
}

var obj = new Developer('Sourabh');
obj.showDetail();

5. Template Literals

Template literals, in ES5 we had to break the string somewhat this —

var fName = 'Sourabh';
var lName = 'Kumar';
var name = 'Welcome ' + fName + ' ' + lName + '.';
var link = 'http://localhost:8080?user=' + fName;

In ES6 we can use a new syntax ${} within the backquote string —

var fName = 'Sourabh';
var lName = 'Kumar';
var name = `Welcome ${fName} ${lName}.`
var link = `http://localhost:8080?user=${fName}`

6. Destructuring

Destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays or properties from objects, into distinct variables.

Using ES5, we use to destructure somewhat like this,

var actor = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

var name = actor.name;
var realName = actor.realName;

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

const actor = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

const { name, realName } = actor;

If the destructured object doesn’t have some property specified in the destructuring assignment, then the variable is assigned with undefined.

Using ES5 destructured approach, the variable contains the property value or can be assigned with default value, i.e

const actor = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

const { name, realName, vigilanteName = 'The Dark Knight'} = hero;
vigilanteName;     // The Dark Knight

To add more to destructuring, this also works with arrays. i.e

var [str1, str2, str3, str4] = str.split('.')

7. Promises

ES5 did not have promises. Libraries had their own custom and non-standard promise implementations. ES6 introduced a standard Promise implementation.

Let’s look at the example of a delayed asynchronous execution with setTimeout() using arrow function.

var promise = new Promise((resolve, reject)=> {
  console.log('Hello world.')  
  setTimeout(resolve, 1000)
}).then(()=> {  
  console.log('Welcome.')
})

Same can be re-written with ES6 promises somewhat like…

var promise =  ()=> new Promise((resolve, reject) => {
  setTimeout(resolve, 1000);
})

promise().then(function() {    
  console.log('Hello world.');    
  return promise();
}).then(function() {    
  console.log('Welcome.')  
})

Click here to read more about promise.

8. Modules

As you might now, there were no native modules support in JavaScript before ES6. Now there are modules with import and export operands.

Let’s say we have port variable and a method getAccounts in ES5 module.js —

module.exports = {  
  port: 8080,  
  getConfig: function() { ... }
}

In ES5, we would use require('module') in our js file to use,

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

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

export var port = 8080;
export function getConfig(url) { ... };

In the importer ES6 file, we use import syntax. For example,

import {port, getConfig} from 'module';
console.log(port); // 8080

ES7 Features

1. Includes

Before ES7, to check if the given array contains an element or not we use to make use of Array.prototype.indexOf().

let numbers = [2, 4, 6, 8];

if(numbers.indexOf(2) !== -1) {  
  console.log('Array contains value');
}

ES7 introduced Array.prototype.includes() to check the array, if the value passed as an argument is present or not, returns true if the array contains the value otherwise, it returns false.

let numbers = [2, 4, 6, 8];

if(numbers.includes(2)) {
  console.log('Array contains value');
}

includes() handles NaN better. If the array contains NaN, then indexOf() does not return a correct index while searching for NaN where as includes() returns the correct value when searching for NaN.

let numbers = [2, 4, ,NaN, 6, 8];
console.log(numbers.indexOf(NaN)); // -1 
console.log(numbers.includes(NaN)); // true

2. Exponentiation Operator

JavaScript has introduced a shorthand method of exponentiation. JavaScript supports many arithmetic operators, e.g +, -, * .

ES7 came up with the exponentiation operator ** which serves the same purpose as Math.pow(). It returns the first argument raised to the power of the second argument.

let base = 3;
let exponent = 4;
let result = base ** exponent;
console.log(result);

ES8 Features

1. Object.entries

Object.entries allows us to get an object’s enumerable property pairs in array format ([key, value]). The ordering of the properties is the same as that given by looping over the property values of the object manually.

const person = {
  name: 'Sourabh',
  designation: 'Developer',
};
for (const [key, value] of Object.entries(person)) {
  console.log(`${key}: ${value}`);
}

2. Object.values

Object.values has been immensely useful for me. It returns an array whose elements are the enumerable property values found on the object. The ordering of the properties is the same as that given by looping over the property values of the object manually.

const person = {
  name: 'Sourabh',
  designation: 'UI Developer',
};

console.log(Object.values(person)); // ['Sourabh', 'Developer']

3. Trailing Commas

JavaScript now accommodates for the extra comma in arrays or parameters to a function. This feature can be useful when adding new elements, parameters, or properties to JavaScript code. If you want to add a new property, you can add a new line without modifying the previously last line if that line already uses a trailing comma.

var arr = ['a', 'b', 'c'];
arr.length; // 3

var arr = ['a', 'b', 'c',,,];
arr.length; // 5

getDetails(name, age,) { ... };

4. Async functions (async and await)

The syntax for async await is actually quite intuitive. async keyword turns a function into a promise, you could refactor your code to use a hybrid approach of promises and await, bringing the second half of the function out into a new block to make it more flexible.

function asyncCallOne() {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log('1. First thing setting up second thing');
            resolve();
        }, 1000)
    })
}

function asyncCallTwo() {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log('2. Second thing setting up third thing');
            resolve();
        }, 1000)
    })
}

async function mainFunc() {
    try {
        await asyncCallOne();
        await asyncCallTwo();
    }
    catch (err) {
        console.error(`ERROR(${err.code}): ${err.message}`);
    }
    finally {
        console.log('End');
    }
}

mainFunc();

. . . . .

Congratulations! You’ve just gone through ES6, ES7, ES8 features which you will be using on regular basis . Now, take a break and let everything you’ve learned today settle down.

Thanks for Reading!!.

Sourabh Sinha

Add comment

Follow us

Feel free to get in touch. I love meeting interesting people and making new friends.

Any suggestions will be appreciated.