5 ES6 features you need to know

Learning any modern frontend framework requires knowledge on some great features of JavaScript ES6. From my experience I thought of sharing 5 features of ES6 that I encountered using most often. So, in this post I will share simple explanation of the following features:

  • let & const
  • Arrow functions
  • Classes
  • Spread & rest operators
  • Destructuring

let & const

Let and const are introduced as new features that serve as a replacement of famous var to declare variables. It is highly recommended to use them in order to avoid accidental mutation of variable values.

let - this should be used to declare a block-scope local variables by optionally initializing it with a value and can be re-assigned to a new value when needed.

There are a few differences between let and var. Let check the major ones:

  • A let variable is scoped to the immediate block scope and not function body as var is:
function foo() {
     let x = 1;
     {
          let x = 2; //not the same variable
     } 
}
  • Let does not create a property in the global object, which it will result as undefined in the global perspective
var x = 1; 
let y = 2;

console.log(this.x); // global
console.log(this.y); // undefined
  • Re-declaring the same variable will result in reference error
let x = 1;
let x = 2; //reference error
  • Declaring a variable without initializing it will result into a reference error instead of undefined
console.log(x); // reference error
console.log(y); //undefined

let x= 1;
var y= 2;

const - is used to declare a constant block-scope (similar to'let') variables and is necessary to be initialized in the same line where it is declared. Also, a constant cannot be changed through reassignment and cannot be re-declared.

const NAME = "ES6" //a read-only reference to a value

For example, when using the React library it is typical to declare functions using const, such as functional-based components.

Arrow functions

Essentially arrow functions are an alternative to creating functions, but apart from the short syntax, it has some differences compared to the regular form.

The syntax of an arrow function is:

// arrow function
const call = (phoneNumber) => { 
    console.log(phoneNumber)
}

// long form 
function(parameter1, parameter2) {
    return value;
}

//when there is only one parameter, brackets can be omitted
const call = phoneNumber => {
    console.log(phoneNumber);
}

//when only one line return statement, curly brackets and return keyword can be omitted
const call = phoneNumber => phoneNumber;

An arrow function does not have its own binding of this which is considered as its main advantage. Also, it does not have binding to super, arguments or new.target keywords which means that they are not suitable as constructors. By the lack of this, the function ends up finding the this from the enclosing scope.

function retryCall(phoneNumber){
   this.counter = 0;

   setInterval(() => {
       this.counter++; // 'this' refers to the retrycall object
   }, 1000);
}

Spread & Rest operator

These two operators have the same syntax, that is "..." (yeah, it's actually three dots) and their naming is based on the context and the way that they are used. So, the spread operator allows to pull out elements of an array, or the properties of an object separately. As an example:

const numbers = [2,4,6];

function findSum(x,y,z) {
   return x + y + z;
}

findSum(...numbers); // that will result into findSum(2, 4, 6);

Whereas, the Rest operator is useful for cloning arrays and objects into a different variable. Since both are reference types, this operator comes in handy to prevent unintentional mutation.

let numbers = [2, 4, 6];

let moreNumbers = [...numbers, 8, 10] // this will result in [2, 4, 6, 8, 10];

Destructuring assignment

This feature allows to easily extract values of array elements or object properties and store them in variables.

//array destructuring
let [a, b] = ['hello', 'world'];
a = 'hello';
b = 'world';

//object destructuring
let {name} = {name : 'john', age: 28};
name = 'john';
age // undefined

This is very useful when working with function arguments. When not using this feature, when one property of an object is needed the whole object needs to be passed in order to have access. However, destructuring allows pulling out only the needed properties, which results into a more condensed code. Consider the following:

function getPhoneNumber(addressBookObj) {
   return addressBookObj.phoneNumber;
}

getPhoneNumber({name : 'John', age: 25, phoneNumber : 223344}); //return the 223344 phone number value

//using destructuring to access only one property of the object
const getPhoneNumber = ({phoneNumber}) => return phoneNumber; 

getPhoneNumber({name : 'John', age: 25, phoneNumber : 223344}); //returns phoneNumber value

Essentially, we get the same result but we save some lines of code by pulling out only the needed property.

I hope you enjoyed this short article and that you'll find it useful to start learning any modern framework.

Any feedback/suggestion/comment is highly appreciated ^_^

Comments (2)

Shishir Bhandari's photo

Regarding the spread and rest operator, why does it have two names when it does the same thing in both cases? It does spread the values in both cases, right ?

Nikolai Kolesnikov's photo

I guess it depends on point of view.

When you declare function it is "rest": function funcName(a, b, ...rest) { console.log(rest); }

When you call function (or fill array, object) and try to pass a few arguments it is "spread":

funcName(...spread); [...spread]; {...spread};