UI Development

Frequently used ES6 features

Introduction

ES6 is a huge JavaScipt update, jumping right from 2011 to 2015. It introduced a bunch of whole new cool features that made things simple and more convenient. If you work with JavaScript on a daily basis, then you might already be familiar with some of these features. But you might not know the features specific to this standard. So, let me go into detail into some of the most used characteristics particular to this standard.

Extended Parameter Handling

  • Default Parameter Values:  In ES6, we can directly assign the default value.

    ES5 code

    function func(height, weight, person) {
        height = height || 6;
        weight = weight || 70;
        person = person || 'Rambo';
        return { height, weight, person };
    }
    ES6 code
    function func(height, weight = 7, person = 42) {
        return { height, weight, person }
    }
  • Rest Parameter: Rest parameter is a new way to handle the function parameter. Irrespective of definition of a function with the help of a rest parameter, a function can be called with any number of arguments.

    function total(...numbers) {
    	let tot = 0
    	for (int n of numbers) {
    		tot + = n
    	}
        return tot
    }
    const sum1 = total(1, 2, 3)  // sum1 = 6 
    const sum2 = total(1, 2, 3, 4)  // sum2 = 10

    Rest operator takes all the left out parameters which are passed in the function call and forms an array with them.

    function show(a, b , ...numbers) {
    	console.log(a, b, numbers)
    }
    show(10, 11, 12, 13) // Output: 10, 11, [12, 13]

    Note: We can’t use Rest parameter in between the parameters like func(a, …numbers, b). This is absurd and throws a syntax error. So, the rest parameter should always be used as the last parameter in the function call.

  • Spread Operator: It helps us to place all the elements of one array into another by using ‘…’ notation before an array:

    var arr1 = [ "hey", true, 9 ]
    var arr2 = [ 1, 2, ...arr1, 10] // [ 1, 2, "hey", true, 9, 10 ]

    Spread operator can also be used for splitting all the characters of a string and converting then into characters:

    var str = "foodie"
    var chars = [ ...str ] // [ "f", "o", "o", "d", "i", "e" ]

Template Literals

  • String Interpolation: This is an intuitive way of writing a string using the combination of variables and it is very helpful for multi-line strings.
    ES6 code

    var customer = "Alexa"
    var cart = { prod_name: "Ice cream", price: 42, units: 2}
    var message = `Hey ${customer},
    		you bought ${cart.units} units of ${cart.prod_name} for
    		a total of ${cart.price * cart.units}`

    ES5 code

    var customer = "Alexa";
    var cart = { prod_name: "Ice cream", price: 42, units: 2};
    var message = "Hello " + customer + ",\n" +
    "you bought " + cart.units + " units of " + cart.prod_name+ " for\n" +
    "a total of " + (cart.price * cart.units);
  • Custom Interpolation: This is an intuitive way of writing a string using a combination of variables and it is very helpful for multi-line strings.
    ES6 code

    var id = "secret"
    var url = `http://localhost:8080/api/tokens/${id}`

Enhanced Object Properties

  • Shorthand property: Shorter syntax for assignment:
    ES6 code

    var x = 1, y = 2
    var position = { x, y }

    ES5 code

    var x = 1, y = 2;
    var position = { x: x, y: y };
  • Computed Property Names: Now in an object definition, computed names are also allowed:
    ES6 code

    function number() {
    	return 2
    }
    let obj = {
        food: "bar one",
        [ "base" + number() ]: 4
    }

    ES5 code

    function number() {
    	return 2;
    }
    var obj = {
        food: "bar one"
    };
    obj[ "base" + number() ] = 4;

Destructuring Assignment

  • Array Matching: In the code below, numbers array is being assigned to [a, , z]. So, a = 10 and z = 50. When we have to interchange the numbers, we can do it in a single line with a temporary variable using this property. The example shows the difference between ES6 code and ES5 code:
    ES6 code

    var numbers = [ 10, 20, 50 ]
    var [ a, , z ] = numbers 
    [ z, a ] = [ a, z ]

    ES5 code

    var numbers = [ 10, 20, 50 ];
    var a = numbers[0], z = numbers[2];
    var temp = a; 
    a = z; 
    z = temp;
  • Object Matching: Easy way of destructuring objects and assigning them to variables:
    ES6 code

    var action = { lhs: 7, rhs: 8, op: 'Multiply' }
    var { op, lhs, rhs } = action

    ES5 code

    var action = { lhs: 7, rhs: 8, op: 'Multiply' };
    var op  = action.op;
    var lhs = action.lhs;
    var rhs = action.rhs;

    In the above example, we saw how easily we can assign similar name variables now let’s look at how we can assign it to new variables:

    var action = { lhs: 7, rhs: 8, op: 'Multiply' }
    var { op: copy_op, lhs: copy_lhs, rhs: copy_rhs } = action

    Here copy_op, copy_lhs and copy_rhs variables get the assigned values of action.op, action.lhs and action.rhs respectively.

  • Deep matching of objects: 

    var action = { lhs: 7, rhs: 8, op: { op1: 'Multiply', op2: 'Add' } }
    var { op: { op1: copy_op }, lhs: copy_lhs, rhs: copy_rhs } = action      // copy_op = 'Multiply'

Arrow Functions

  • Expression Bodies: New syntax of the fat arrow(=>) reduces the effort of writing a function and is more intuitive for the developer.
    ES6 code

    even_numbers = [2, 4, 6, 8, 10]
    odd_numbers  = numbers.map(v => v + 1)
    number_pairs = numbers.map(v => ({ even: v, odd: v + 1 }))

    ES5 code

    even_numbers = [2, 4, 6, 8, 10];
    odd_numbers  = even_numbers.map(function (n) { return n + 1; });
    number_pairs = even_numbers.map(function (n) { return { even: n, odd: n + 1 }; });
  • Statement Bodies: Another intuitive way of using the arrow function,
    ES6 code

    numbers = [5, 7, 8, 10, 11]
    multiples_of_five = []
    numbers.forEach(n => {
        if (n % 5 === 0) {
           multiples_of_five.push(n)
    	}
    })

    ES5 code

    numbers = [5, 7, 8, 10, 11]
    multiples_of_five = []
    numbers.forEach(function (v) {
       if (v % 5 === 0)
           multiples_of_five.push(v);
    });

Classes

  • Classes are just a special type of function, but the main difference is functions are hoisted and classes are not hoisted.

  • In ES6 we can encapsulate everything into a single entity which is more intuitive in nature.
    ES6 code

    class newStudent {
    	constructor(newRollno, f_name, l_name){
    		this.assignRollno(newRollno)
    		this.fname = f_name
           	this.lname = l_name
        }
    	assignRollno(newRollno){
            this.rno = newRollno
        }
    }

    ES5 code

    var newStudent = function (newRollno, f_name, l_name) {
        this.fname = f_name;
      	this.lname = l_name;
    	this.assignRollno(newRollno);
    };
    Shape.prototype.assignRollno = function (newRollno) {
        this.rno = newRollno;
    };

Modules

  • A module is nothing but a snippet of code written in a file. This helps in organising the set of reusable code in a particular file.

  • Before ES6, there was no native modules support. Now as there is support, it helps to increase the code reusability.

  • Export statements with named exports:

    export comp1
    export comp2
  • Exporting multiple files under a single export statement:

    export {comp1, comp2, comp3}
  • Modules which require only a single value export can use export default.  There can be only one default export/module.

    export default comp
  • Importing named exports:

    import {comp1, comp2, comp3} from someModule
  • Importing named exports and renaming them:

    import {comp1 as component1}  from someModule
  • To import all named exports use *.

    import * as someVar from someModule
  • Importing named exports:

    import {comp1, comp2, comp3} from someModule
  • Importing named exports and renaming them:

    import {comp1} as component1  from someModule

Promise

  • Example of promise:

    let p = new Promise(function(resolve,reject){
       if (workDone) {      
    	  resolve('success work	promise completed')
       } else {
          reject('ERROR , work promise could not be completed')
       }
    })
  • Chaining of promises is done when there is a sequence in which the async calls have to be made

    function addPositiveNosAsync (num1, num2) {
        let prom = new Promise ((resolve, reject) => {
            if (num1 >= 0 && num2 >= 0) {
                resolve(num1 + num2)
            } else
                reject('Not a positive number')
        })
        return p;
    }
     
    addPositiveNosAsync(10, 20).then(result => {
        console.log("1st result ", result)      //1st result 30
        return addPositiveNosAsync(result, result)
    }).then(result => {
        console.log("2nd result ", result)     //2nd result 60
        return addPositiveNosAsync(result, result)
    }).then(result => {                                                       
        console.log("3rd result ", result)     //3rd result 120
    })
  • Promise.all helps to aggregate all the promises and to show the result.

    function addPositiveNosAsync (num1, num2) {
          let prom = new Promise((resolve, reject) => {
             if (num1 >= 0 && num2 >= 0) {
                resolve(num1 + num2)
             }
             else
                reject('Not a positive number')
          })
    
          return p;
       }
    
    Promise.all([addPositiveNosAsync(40, 20), addPositiveNosAsync(60, 10)])
       .then(value => {
          console.log(value[0])  // 60
          console.log(value[1])  // 70
       })

Conclusion

In this blog, I have covered frequently used features in ES6 and given you a proper insight into the very specific characteristics of this standard. For further reading, you can visit the below sites:

https://codetower.github.io/es6-features/

http://es6-features.org/

About The Author