paint-brush
4 Modern JavaScript (ES6+) Features You Need To Useby@mosh
1,362 reads
1,362 reads

4 Modern JavaScript (ES6+) Features You Need To Use

by Mosh HamedaniJanuary 8th, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

This is not a comprehensive list of all the new features since ECMAScript 2015 (ES6) But these are the 20% of features that you use 80% of the time. These features include: Template literals (previously called template strings) and arrow functions. Arrow functions give you a clean and concise syntax for writing function expressions. This article is a work in progress. I’ll be adding more features to this list. For now, I want to publish this today!

Company Mentioned

Mention Thumbnail
featured image - 4 Modern JavaScript (ES6+) Features You Need To Use
Mosh Hamedani HackerNoon profile picture

JavaScript has progressed a lot over the past few years. Whether you are new to JavaScript or have some experience and want to quickly get up to speed with the most commonly used features in modern JavaScript, this post is for you.

In this article, I’m going to share with you the features I use on a daily basis. These features include:

  • Template literals
  • let
     and 
    const
  • Arrow Functions
  • Destructuring

This is not a comprehensive list of all the new features since ECMAScript 2015 (ES6). But these are the 20% of features that you use 80% of the time. Plus, this article is a work in progress. I’ll be adding more features to this list. For now, I want to publish this today!

All these new features are natively supported in all modern browsers. If you want to try out any of the code snippets below, simply open up Chrome Developer Tools and type the code.

So, let’s get started!

Template Literals

Before ES6, we had to deal with these ugly string concatenations:

var name = 'Mosh'; 
var message = 'Hi ' + name + ',';

Now, with template literals (previously called template strings), we can define a string with placeholders and get rid of all those concatenations:

var name = 'Mosh'; 
var message = `Hi ${name},`;

Note that I’m using the backtick character here. As funny as it sounds, nobody knew what backticks were until Angular 2 was released! That’s the character before number 1 on your keyboard.

To add a placeholder in a template literal, we use the ${expression} syntax. You can replace “expression” with any JavaScript expressions. Here, we are adding the name variable there. You can also call a function or pass any JavaScript expressions that result in a value.

Another benefit of using template literals is that they can expand multiple lines. They are particularly useful when composing email messages:

var message = `
Hi ${name},
Thank you for joining my mailing list. 
Happy coding,
Mosh
`;

let and const

Prior to ES6, we used the 

var
 keyword to define variables. The scope of a variable defined using the 
var
 keyword is the entire enclosing function. Here’s an example:

function doSomething() {
   for (var x = 0; x < 5; x++) { 
      // Technically, x should only be scoped to this block because this is 
      // where we have defined x. 
   }
   // But it turns out that x is available here as well! 
   console.log(x); // 5 
}

That’s not how most if not all other programming languages behave! Variables defined within a block should be scoped to that block only. In this example, 

x
 should not be accessible outside of the 
for
 block.

Another issue with the 

var
 keyword is that if you use it at the top level outside of a function, it creates a property on the global object:

var x = 1; 
console.log(window.x); // 1

ES6 introduced 2 new keywords for resolving these issues: 

let
 and 
const
. Both these keywords define variables that are scoped to the containing “block” not “function”:

function doSomething() {
   for (let x = 0; x < 5; x++) { 
      // With the "let" keyword, now x is only accessible in this block.
   }
   // x is out of the scope here
   console.log(x); // x is not defined  
}

With 

const 
we can define a constant. So we cannot reassign it later:

const x = 1; 
x = 2; // throws "Assignment to constant variable."

Also, unlike the 

var
 keyword, 
let
 and 
const
 don’t create a property on the global object if you use them at the top level:

let x = 1; 
console.log(window.x); // undefined

So, here is what you should take away:

Ditch the 

var
 keyword. Use only 
let
 and 
const
.

Prefer 

const
 to 
let
. Use 
let
 only if you need to re-assign the identifier; otherwise, use 
const
 to prevent accidentally re-assigning a constant.

Arrow Functions

My favorite feature in ES6! Inspired by lambda expressions in C#, arrow functions give you a clean and concise syntax for writing function expressions. Here’s a function expression in ES5:

const square = function(number) { 
   return number * number; 
}

With arrow functions, we get rid of the 

function
 keyword and put a fat arrow 
=>
 between the parameters and the body of the function:

const square = (number) => { 
   return number * number; 
}

If our function is a one-liner and returns a value, we can drop the 

return 
keyword as well as the curly braces:

const square = (number) => number * number;

Isn’t that much cleaner and more concise than the former syntax?

But wait, we can make this even shorter: If our arrow function includes only a single parameter, we can even drop the parenthesis:

const square = number => number * number;

What if our arrow function doesn’t have any parameters? We need to use a pair of parenthesis:

const sayHello = () => { console.log('hello'); };

Arrow functions are particularly useful when you need to pass callback functions as arguments:

// ES5
var activeJobs = jobs.filter(function(job) { 
    return job.isActive; 
});
// ES6
const activeJobs = jobs.filter(job => job.isActive);

Arrow functions, unlike normal functions, don’t rebind 

this
. Does this pattern look familiar to you?

// ES5
function onSubmit() { 
    // Keep a reference to "this" so we can use it in the inner function below. 
    var that = this; 
    orderService.store(order, function(result) { 
       // In JavaScript, ever function defines its own "this" value. So, "this" in this inner function 
       // here is different from "this" in the onSubmit() function. That's why we had to keep a 
       // reference to "this" and store it in "that". Now, we can use "that": 
       that.result = result; 
    });
}

Arrow functions, unlike normal functions, don’t rebind 

this
. They use the 
this
 value of the enclosing execution context. So, if we replace the inner function above with an arrow function, we don’t need to keep a reference to 
this
 anymore.

// ES6
function onSubmit() { 
    orderService.store(order, result => { 
       // Since we're using an arrow function here, "this" references the "this" value of the containing function
       // (onSubmit). Arrow functions don't re-define "this". 
       this.result = result; 
    });
}

Destructuring

Destructuring is an expression that allows us to extract properties from an object, or items from an array. Let’s say we have an address object like this:

const address = { 
   street: '123 Flinders st',
   city: 'Melbourne',
   state: 'Victoria'
};

Now, somewhere else we need to access these properties and store their values in a bunch of variables:

const street = address.street;
const city = address.city; 
const state = address.state;

We have this repetitive code over and over: “address.” repeated 3 times. Object destructuring gives us a short and clean syntax to extract the value of multiple properties in an object:

const { street, city, state } = address;

That’s it! This code is exactly equivalent to the snippet above. We use curly braces on the left to destructure the address object. Inside the braces, we’re defining 3 variables: streetcity, and state. Their values will be extracted from the corresponding properties in the address object.

Note that we don’t have to list all the properties in the address object. Maybe we’re interested only in the street property:

const { street } = address;

Object destructuring is particularly useful when you’re dealing with nested objects:

const person = { 
   name: 'Mosh', 
   address: {
      billing: { 
         street: '123 Flinders st',
         city: 'Melbourne',
         state: 'Victoria'
      }
   }
};

Without destructuring, we would have to write this ugly and repetitive code:

const street = person.address.billing.street;
const city = person.address.billing.city;
const state = person.address.billing.state;
// So annoying!

Now, we can achieve the same result using a single line of code:

const { street, city, state } = person.address.billing;

We can also destructure arrays but we use square brackets ([]) instead of curly braces ({}). Let’s say we have an array and we want to extra the first and second item and store them in two different variables:

// ES5
const values = ['John', 'Smith'];
const first = values[0];
const last = values[1]; 
// ugly!

With destructuring, we can re-write the above code like this:

// ES6
const values = ['John', 'Smith'];
const [first, last] = values;

If you are looking to learn JavaScript in depth, I highly recommend Mosh’s JavaScript courses. The link to all of the courses are below: