10 Important ES6 Features In JavaScript That Makes Your Life Easy
According to Wikipedia, JavaScript often abbreviated as JS is a programming language that conforms to the ECMAScript specification. JavaScript is high-level, often just-in-time compiled, and multi-paradigm. It has curly-bracket syntax, dynamic typing, prototype-based object-orientation, and first-class functions.
After ECMAScript 6 (ES6), JavaScript itself has been a massive changed in the history of the language. In this article, I will show you the interesting things that actually JavaScript makes our life easier than before.
So let’s get started!
Here’s the list of 10 features that, I think, I need to discuss on this blog that might help you understand.
- Hoisting Variables
- Block-Binding: Let and Const
- Default Parameters
- Rest and Spread Parameters
- Arrow Functions
- Destructuring Assignment
- Promises
- Classes
- Enhanced Object Literals
- Template Literals
- Hoisting Variables
Hoisting is a JavaScript default behavioral mechanism in which variable
and function
declarations are moved to the top of the current scope before code executing.
We can see in the JavaScript lifecycle of variables processing that there are three parts such as the declaration, initialization or assignment, and usage like the following picture.
We can not use or initialize any variable
before the declaration and also it has to be maintained at the scope level.
var a = 5;function hoisting() {
a = 1;
var b = 2;
}
hoisting();
console.log(a);
/*
This is valid and considerable as a global variable outside hoisting() function
Result is 1
*/console.log(b); // Error
/*
This is not accessible as a global variable because it is declared inside hoisting() scope
*/
Let’s see another example of a function
declaration.
// function declaration
function student(name, id) {
return `Name is ${name} and id is ${id}`;
}let result = student('Mostafa', 101);console.log(result);
// Name is Mostafa and id is 101
It is a regular function that works well. It also will work well if I declare the function
after calling the function
because of its declaration itself, not expression. Let’s see.
let result = student('Mostafa', 101);console.log(result);
// Name is Mostafa and id is 101// function declaration
function student(name, id) {
return `Name is ${name} and id is ${id}`;
}
But now if I assign a function to a variable
, it is considered as a function expression
and it is not to use before the initialization
let result = student('Mostafa', 101);console.log(result);
// Name is Mostafa and id is 101// function expression
const student = (name, id) => {
return `Name is ${name} and id is ${id}`;
}
// Uncaught ReferenceError: Cannot access 'student' before initialization
Here the student is aconst
variable but it is used before initialization. So it returns areference error
.
But now if I initialize students at first then use it, it can be accessible. Let’s see!
// function expression
const student = (name, id) => {
return `Name is ${name} and id is ${id}`;
}let result = student('Mostafa', 101);console.log(result);
// Name is Mostafa and id is 101
2. Block-Binding: Var, Let, and Const
Variable declarations havingvar
are considered as if they are at the top of the function
or it is treated as a global scope if it is declared outside of a function
.
For making a clear idea about that, consider the following function definition:
function getName(name) {
if (name) {
var result = `Hello ${name}`;
return result;
} else {
// result exists here with a value of undefined
return null;
}
// result exists here with a value of undefined
}
Here we can see that var
is declared in if block scope that is not a global scope but in JavaScript engine, behind the scene the getName
function itself has been changed to like this;
function getName(name) {
var result;
if (name) {
result= `Hello ${name}`;
return result;
} else {
return null;
}
}
That is why we can access it in else
block scope as well as getName
function scope. But it is not a global variable that is accessible globally.
Now if we use let
instead of var
, the situation is changed dramatically. Let’s see an example,
function getName(name) {
if (name) {
let result = `Hello ${name}`;
return result;
} else {
// result does not exist here
return null;
}
// result does not exist here
}
It is because of ES6 let
behavior as JavaScript engine does not permit let
to be hoisted at the top level of the current block scope. Another difference var
andlet
is that let
can not be redeclared like var
For example,
var num = 1;let num = 2;
// Throw an error if (condition) {
let num = 3;
// Does not throw any error
}
Here first let
is not accessible because of num
redeclaration but second let
is valid because it is inif
block scope.
3. Default Parameter
A default parameter means when a named parameter is passed by no value or undefined,
it allows the named parameters to be initialized with default values at the time of function declaration.
function modulus(a, b) {
return a % b;}
modulus(5, 2); // 1
modulus(5); // NaN
The second result is NaN
because all the argument's requirements are not fulfilled.
But when we assign a value to b
by condition, it works well.
function modulus(a, b) { b = (typeof b !== 'undefined') ? b : 2 return a % b;
}
modulus(5, 2); // 1
modulus(5); // 1
Basically, the default parameter helps us to handle NaN
value in this instance when a user does not fulfill all the input fields.
Let’s see a real example of that!
function modulus(a, b = 2) { return a % b;
}
modulus(5, 2); // 1
modulus(5); // 5
I think it is now more clear about that.
4. Rest and Spread Parameters
The most surprisingly topic to me the rest and spread because these look exactly the same each other but meaning is totally different. The syntax is that (...
) and its presentation relies only on where it is used, how it is used. It's more confusing sometimes to developers when it is seen in the code snippet.
I will try my level best to show you the usages in different situations easily.
Spread Operator is unpacking the collected elements such as arrays into single elements. But Rest Operator is collecting all remaining elements into an array or object.
For example,
const arrOne = [‘I’, ‘love’, ‘Programming’]const arrTwo = [‘Programming’, ‘is’, ‘life’] const arr3 = [arrOne, arrTwo];console.log(arr3);
// [ [ ‘I’, ‘love’, ‘Programming’ ], [‘Programming’, ‘is’, ‘life’]]
It’s normal usage of array concatenation. Now I am using Spread (...
) on the array to unpack the array look-a-like [[,,],[,,]]
=> [,,,,]
const arrThree = [...arrOne, 'and', ...arrTwo]console.log(arrThree);
// [ 'I', 'love', 'Programming', 'Programming', 'is', 'life']
Now I use rest (...
) on the array [ ]
// Destructuring arrOne
const [idx1, ...restArrValue] = arrOne;console.log(idx1, restArrValue);
// I [ 'love', 'Programming' ]
Again spread for unpacking the array
console.log(idx1, ...restArrValue);
// I love Programming
Now I will show you the rest and spread usages in an object meaning the same as before.
Let’s create an object as usual.
const person = {
name: 'Mostafa',
age: 30,
gender: 'male',
status: 'developer'
}
Now I assign a new property to the object and use a spread operator for unpacking the object person
const updatePerson = { // spread for unpacking the object { { }, { }} ===> { }
...person,
degree: 'MSC'}console.log(updatePerson);
/*
{
name: 'Mostafa',
age: 30,
gender: 'male',
status: 'developer',
degree: 'MSC'
}
*/
Again using rest operator to the updated object updatePerson
const {
name,
...restObjValue
} = updatePerson;console.log(name, restObjValue);
// Mostafa { age: 30, gender: 'male', status: 'developer' }
I hope, it makes sense to you the usages of rest and spread operator in JavaScript ES6.
5. Arrow Functions
An arrow function expression is a compact alternative to a traditional function expression, but is limited and can’t be used in all situations according to MDN.
An arrow function is used in an only function expression
const add = (num1 = 0, num2 = 2) => {
return num1 + num2;
}console.log(add(undefined, 1)); // 1
console.log(add(1)); // 3
Return a single statement, no need for curly braces { }
, and return keyword
const multiply = (num1 = 0, num2 = 2) => num1 * num2;console.log(multiply(undefined, 1)); // 0console.log(multiply(1)); // 2 const area = (length, width) => length * width;
console.log(area(5, 3)); // 15
When a single/only one parameter is used, there is no need to use bracket ()
const modulus = num1 => num1 % 3;console.log(modulus(1)); // 1
console.log(modulus(3)); // 0
When there is no parameter, use bracket ()
const selfItem = () => 1;
console.log(selfItem());
If you create a function in an object, there is no need to use arrow function. For example,
const bio = {
name: 'Mostafa',
age: 29,
profession: 'Web Developer',
showBio: function () {
console.log(this);
/* Here this means the full object itself. Output is:
{
name: 'Mostafa',
age: 29,
profession: 'Web Developer',
showBio: [λ: showBio]
}
*/
return `This is ${this.name}
and I am ${this.age}.
I am a ${this.profession}.`
}
}console.log(bio.showBio());
// This is Mostafa and I am 29. I am a Web Developer.
These all are the usages of arrow function in diffrenet angles as well.
6. Destructuring Assignment
The destructuring assignment syntax means that it is a JavaScript expression that unpack values from arrays, or properties from objects, into a different variables. In other words, destructuring is the pulling out of the values from an array or properties from an object. Thats it.
Here I will show you the examples of both usages as array destructuring and object destructuring. So let’s get started!
Array destructuring examples:
const myBio = ['Mostafa', 29, 'Web Developer'];
You have to maintain the chronological order in the array like;
const [name] = myBio;
const [, age] = myBio;
const [, , profession] = myBio;console.log(name); // Mostafa
console.log(age); // 29
console.log(profession); // Web Developer
Also, you can destructre all the variables in the array and use them
const [name, age, profession] = myBio;
So index-variable order maintain must be followed in array destructuring.
Destructuring with rest operator that I have discussed above is like that
const friendsArray = ['a', 'b', 'c', 'd', 'e']
const [bestFriend, ...averageFriends] = friendsArray; console.log(bestFriend); // a
console.log(averageFriends); // [ 'b', 'c', 'd', 'e' ]
Object destructuring examples:
const objBio = {
userName: 'Mostafa',
id: 001,
status: 'Developer',
shareBio: {
facebook: true,
twitter: true,
}
}const { userName, id, status, isMarried} = objBio;console.log(userName, id, status, isMarried);
// Mostafa 1 Developer true
You can use nested destructuring as like below;
const { shareBio: { facebook, twitter } }= objBio;console.log(facebook, twitter);
// true true
Also, note that you do not have to use in chronological order like array destructuring.
Hope, it make sence to you!
7. Promises
One of the most powerful features of JavaScript is how it handles itself asynchronous programming in this easiest way. As JavaScript initiated as a language basically for the web, it had to be able to respond to user interactions asynchronously such as clicks, hovers, key presses and so on.
Let’s see a rather trivial example of a delayed example of asynchronous execution with setTimeout()
const processData = () => {
setTimeout(() => {
console.log(1); // after 1 second
setTimeout(() => {
console.log(2); // after 2 second
setTimeout(() => {
console.log(3); // after 3 second
}, 1000);
}, 1000);
}, 1000);
}processData();
To handle this bad practice, Promise is used
const promiseData = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
reject(Error('Error...'));
}, 1000);
});
console.log(promiseData); promiseData.then(data => {
console.log(data);
})
.catch(error => console.log(error));
8. Classes
JavaScript classes that is introduced in ECMAScript 2015 (ES5) are generally called syntactical sugar over JavaScript ‘s existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.
When class is instantiated with ‘new’ keyword, constructor is running automatically.
class Student {
constructor(id, name, age) {
this.id = id;
this.name = name;
this.age = age;
this.lang = [];
this.country = 'Bangladesh';
}getInfo() {
return `
id - ${this.id}
name - ${this.name}
age - ${this.age}
language -${this.lang.join(', ')}`;
}
Now you can instantiate any object using this class constructor
const student1 = new Student(1, 'Mostafa', 29);
console.log(typeof (student1)); // objectconst student2 = new Student(2, 'Mahmud', 30);console.log(student1);
/*
Student {
id: 1,
name: 'Mostafa',
age: 29,
country: 'Bangladesh'
}
*/console.log(student1.name); // Mostafa
When you need full data, just call getInfo()
console.log(student1.getInfo());
That’s the basic idea of class constructor in ES6 as well.
9. Enhanced Object Literals
A JavaScript object literal is a comma-separated list of name-value pairs wrapped in curly braces. Object literals encapsulate data, enclosing it in a tidy package. This minimizes the use of global variables which can cause problems when combining code.
If property and value is the same name, no need to use repeatedly
function bio({
firstName,
lastName,
coveredField
}) {
return {
firstName,
lastName,
commonLang: ['html', 'css', 'js', 'c', 'c++'];
coveredField() {
return `My first name is ${this.firstName},
second name is ${this.lastName}
and I covered ${coveredField}
`;
}
}
}const myBio = bio({
firstName: 'Mostafa',
lastName: 'Mahmud',
coveredField: 'ES6'
});console.log(myBio.firstName); // Mostafa
console.log(myBio.commonLang); // ['html', 'css', 'js', 'c', 'c++']
console.log(myBio.coveredField());
// My first name is Mostafa, second name is Mahmud and I covered ES6
10. Template Literals
According to MDN, “Template literals are string literals allowing embedded expressions. You can use multi-line strings and string interpolation features with them.”
Here is an example of practical usage:
const firstName = 'Mostafa';
const profession = 'developer';
const workField = 'wep application'function modify(strings, ...restValues) { console.log(arguments);
// all data (static and dynamic) in [[array], array] console.log(strings, restValues);
// divided array in output [static data array], [dynamic data array]
let str = ''; strings.forEach((string, i) => { str += `${string} <b> ${restValues[i] || ''}</b>`; }); return str;}
ES6 Tagged Template Literals to modify dynamic data in the template string. Tag functions modify()
don’t even need to return a string always!
const html = modify ` <h1> This is ${firstName.toUpperCase()}</h1> <p> I am a ${profession}</p> <p> I am working on ${workField}</p> `document.body.innerHTML = html;
That's all about ES6 important features that developers face and explore in their JavaScript programming life.
If this article is helpful for you, please do not clap for this.
Enjoy your coding!