ES-6 — Beginner’s Guide — Part 2

ankita srivastava
8 min readMay 28, 2019

I will be covering below topics as the PART-2 section of ECMAScript-6 Beginner’s guide. Here is the PART-1 section link https://medium.com/@srivastavaankita080/ecmascript-6-beginners-guide-60ac3d6c5ac8.

  • What is Destructured Assignments, Rest Parameters, Default Parameters?
  • Working with Arrow Function, Promises & Fetch, Async & Await.
  • ES6 class syntax & Inheritance

So, let’s start with the above topics and explore more into ES6.

Destructured Assignments

Destructured Assignments are performed on arrays & objects. It is quite clear from its name i.e. you will destructure the values present inside the array/objects.

For Arrays destructuring, it will match the index positioning of values.

const employee= ['John', 'Peter', 'Mark', 'Frank', 'Tom'];
const [first,,third,,,] = employee;
console.log(first,',', third);
Output: John, Mark

if there is no requirement exist where you need entire array then you can have this way of destructuring:

const [first,,third,,,] = ['John', 'Peter', 'Mark', 'Frank', 'Tom'];
console.log(first,',', third);
Output: John, Mark

In Object destructuring, it will match the values of the object to the keys instead of index positioning.

const person = {
firstName: 'John',
lastName: 'Peter',
age: 23,
gender: 'Male',
qualification: 'BCA'
};

function printPersonDetails({firstName, age, qualification}) {
return `${firstName} is ${age} years old and is qualified in ${qualification}.`
}

console.log(printPersonDetails(person));
Output: John is 23 years old and is qualified in BCA.

Rest Parameters

Rest parameters allow passing as many parameters as you want. If there is unknown no. of parameters, this can be very helpful. It basically holds all the passed arguments in an array and then you can access it in following way.

function addNumbers(...numbers){
let sum=0;

console.log(numbers[0]);
console.log(numbers[1]);
console.log(numbers[2]);

for(let number of numbers){
sum += number;
}

console.log(`sum of all numbers ${sum}`);
}

addNumbers(1,2,3);
addNumbers(1,2); /*as there is not 3rd argument it will print undefined */
Output: 1
2
3
sum of all numbers 6
1
2
undefined
sum of all numbers 3

Default Parameters

Default parameters are the parameters which already have default values. So while using the default parameters if you are not assigning any values, it will not give undefined results because the default value is always there as output.

function printPersonDetail(name = 'John', age= 23){
console.log(`${name} is ${age} years old.`)
}

printPersonDetail();
Output: John is 23 years old.

Arrow Functions

In ES5 we used function keyword for creating functions, which got changed with ES6. Now we can create functions using arrow function ( => ) and the syntax is quite handy!!

Let’s have a comparison of function syntax in both ES5 & ES6 way to get more clarity.

In ES5

const printPersonDetail = function(name, age){
console.log(`${name} is ${age} years old.`)
};
printPersonDetail('John',23);

In ES6

const printPersonDetail = (name = 'John', age= 23) => console.log(`${name} is ${age} years old.`);

Make sure to add curly braces after arrow function if you have more than one line of code in your function.

Arrow function brings a lot more conciseness and readability in your code. Unlike in normal function, it eliminates the need for binding this keyword. In arrow function, this keyword will always have meaning from its original context so you don’t need to go & do explicit binding of this keyword.

Promises & Fetch

Promises are objects which handles asynchronous operations and results in resolution or rejection. We can add multiple conditions depending on promise resolution or rejection value using then keyword. A promise can be in any of the 3 states at a time:

a.) pending -> execution of promise started but not yet fulfilled or rejected.

b.) fulfilled -> execution of promised completed successfully.

c.) rejection -> execution of promise failed because of some error.

Fetch function is used for loading data from an API. It takes 2 parameters, the first one is the API itself and the second one is an object, from which you can change the different setting while loading data.

Generally, you will find promise usages more with fetch but there are other ways also. let’s see an example of using fetch with a promise to see its practical usage:

const data = () => {
return fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.ok ? response.json() : Promise.reject())
.then(json => { return `${json.title} is completed or not ? -> ${json.completed}`})
};

data().then(console.log)

So, what is happening here is :

  1. data is a variable which is holding the value being returned by fetch call.
  2. fetch is calling a random API, and if the fetching of data from https://jsonplaceholder.typicode.com/todos' is successful ( status = 200 ok) then the promise is resolved and you will get data in JSON format and you will move to other then statement where we are returning the message. Promise will be in the fulfilled state.
  3. if suppose there is some error in fetching the data from the above API then it will reject the promise (Promise.reject()). Promise will be in rejection state.
  4. once the promises in fetch are handled then it will move to last then statement which will print the value of data returned by fetch call.

There are a lot more we can do with the JSON data that we get after promise resolution or rejection. For Example:

const data = () => {
return fetch('https://jsonplaceholder.typicode.com/')
.then(response => response.ok ? response.json() : Promise.reject())
.then(json => json.filter(user => user.title === 'delectus aut autem')[0])
.then(msg => { return `${msg.title} is completed or not ? -> ${msg.completed}`})
.catch(status => { return status} )
};

data().then(console.log)

If any error occurs while fetching the response it stops its execution of then and moves to catch block.

Async & Await

async keyword is used for asynchronous function. Now, the asynchronous function is something whose execution flow is not dependent on the main program flow i.e., it might have some parallel code execution. But its code is quite similar to a normal function, just we need to write async keyword at the start of the function to indicate that this function is asynchronous in nature.

So now we understood async functions and it may be possible that executing any particular line of the asynchronous function(say X) takes more time and there will be some other code(say Y) dependent on the result of function X. Here comes the need to await keyword. await keyword can be used here to pause or wait for any further code execution till that particular line code execution finishes successfully. Let’s have a look at the code to understand it practically.

const data = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
const value = await response.json();
console.log(value);
};
data();

In the above example, data is an asynchronous function as its flow of execution is not synchronous( because fetch call & converting the response to JSON response might take more time than other lines of code present in data function) so for indicating that we used the async keyword.

We used await before the fetch call because we want to pause the execution of converting the response to JSON response(response.json()) till the successful execution of fetch call otherwise response variable will be holding undefined which results in an undesired result.

ES6 Class Syntax & Inheritance

ES6 classes offer much cleaner and better syntax for writing code and handling inheritance compared to ES5 way of writing classes. It simply provides a better syntax for dealing with the prototype(e.g., adding function to prototypes, prototype inheritance) but does not introduce any new object-oriented model to JS.

ES5 way of writing classes:

var Dog = function(name , color) {
this.name = name;
this.color = color;
};
Dog.prototype.getDogDetails = function(){
return `${this.name} is ${this.color} in color.`
};

var dog = new Dog('Tom', 'White');
console.log(dog.getDogDetails());

So here you wrote a function Dog which is basically acting as a fake class, and then for writing function, we need to add getDogDetails function to the prototype of Dog function.

But in ES6. the syntax is quite cool & easy to write:

class Dog {

constructor(name, color) {
this.name = name;
this.color = color;
}

getDogDetails() {
return `${this.name} is ${this.color} in color.`;
}
}

let dog = new Dog('Tom', 'White');
console.log(dog.getDogDetails());

We are creating a Dog class using the class keyword. name & color are the constructor properties of Dog class. In the background, the getDogDetails function is assigned to the Dog class prototype which is handled by ES6, we don’t need to do it explicitly which results in quite clearer code.

So, now you can compare how ES6 reduces our effort of creating the class. When it comes to inheritance, ES6 way of writing class is like a boon as it saves us from writing complex code with nasty syntax. Let’s see an example to compare the way of inheritance done in ES5 v/s ES6:

var Dog = function(name , color) { /* step1 */
this.name = name;
this.color = color;
}; /* step1 finished */

Dog.prototype.getDogDetails = function(){ /* step2 */
return `${this.name} is ${this.color} in color.`
}; /* step2 finished */

var WhiteDog = function (name, color) { /* step3 finished */
this._super.call(this, name, color);
}; /* step3 finished */

WhiteDog.prototype = Object.create(Dog.prototype); /* step4 */

WhiteDog.prototype.constructor = WhiteDog; /* step5 */

WhiteDog.prototype._super = Dog; /* step6*/

var whiteDog = new WhiteDog('Tom', 'White');
console.log(whiteDog.getDogDetails());

I know the above code is a bit clumsy 😕 . Let me explain this so that you can understand the effort that got reduced with ES6 class syntax.Step1 & Step2 should be clear to you as I already explained it in the above example.

  1. Step 3 is the creation of WhiteDog class in ES5 way, this._super.call(this, name, color); is used to pass the variable value to its superclass. We are calling call method & passing this keyword so that new context(specific to child class) of this is set.
  2. In step 4, we are setting the Child class prototype to be equal to Parent class.
  3. In step 5, we are assigning child class constructor to its own prototype.
  4. In step 6, we are assigning the Dog class as the superclass for WhiteDog class.

Now, let’s see ES6 way of writing class:

class Dog {

constructor(name, color) {
this.name = name;
this.color = color;
}

getDogDetails() {
return `${this.name} is ${this.color} in color.`;
}
}

class WhiteDog extends Dog {
constructor(name, color){
super(name, color);
}
}

let whiteDog = new WhiteDog('Tom', 'White');
console.log(whiteDog.getDogDetails());

Let we walk through the code once to explain to you:

  1. A Dog is the Parent class which has a name and color property and getDogDetails behavior in it.
  2. WhiteDog is the child class which is inheriting parent class by using extends keyword & because of that, a child class can use parent class properties & behavior.

Cool!! This code looks quite neat & clean & easy to understand 😊 . Now, I guess you can clearly see how much effort got reduced because of ES6 class syntax.

So, I covered all the topics that are required to start working with ES6 & I hope you enjoyed it. ES6 is quite popular these days but yet there are some ES6 syntax which is not yet supported by some browsers and for that we need to do transpiling of our ES6 code. It's just converting the ES6 code that you wrote to ES5 so that browser supports it and a lot of tools are available for it like babel etc. Let me know if you want me to write, for setting up the babel tool for ES6 transpiling. Happy coding 😊 😊

--

--