10 ES6 JavaScript features you must know, and one that you won't ever use in web projects

Marcin Kwiatkowski /
10 ES6 JavaScript features you must know, and one that you won't ever use in web projects

This time I would like to show the commonly used EcmaScript 6 features, and at the end – the one (which is popular) that you probably won't use in a typical web (frontend) project based on React or Vue.

Commonly used features:

  1. const and let

  2. promises

  3. rest and spread operator

  4. template literals

  5. destructuring

  6. default values for function parameters

  7. arrow functions

  8. object literal shorthand

  9. imports/exports (modules)

  10. The for/of loop

The one that you won't use:

  1. Classes, including class components, inheritance

you don't need to define class to get object instance

Let's dive into it, but before we start, let's answer the question:

What exactly is EcmaScript?

Let's think about it like something that defines standards and rules. For example, in the automotive industry in Europe, we have vehicle emission standards for exhaust emissions like Euro 4, Euro 5, Euro 6, Euro 6b, etc. For example, each new passenger car produced in 2022 must comfort to the Euro 6d standard.

EcmaScript standards

In JavaScript, we have EcmaScript, a standard(it defines rules) for JavaScript code. When you go to the EcmaScript website, you will see that there are many standards like:

  • ES 4

  • ES5

  • ES 6

  • ES 2015

  • ES 2016

  • ...

  • ES 2021

  • ES Next

Basically, before ES 6, there was ES 5 long time, and when they announced ES6, the tempo became more dynamic. :) Anyway, ES 6 is a breaking change, which changed a lot for JavaScript developers.

ES6+ and browsers support

The main problem with the transition from ES5 to ES6 was browser support (still for new standards). Code written in ES6 did not work in browsers. For example, now I see that popular browsers support ES 2015 features, but we now have ES2021.

Long-story-short: some new features work in browsers, others don't, and we as developers don't want to overthink things like that. We want to write a code and see the results. There is a way to transpile ES6+ code to es5 and be sure that it will work in any browser that we want.

How to convert ES6+ code to ES5 that browsers know

BabelJS is the most famous JS transpiler that can convert any ES6+ code to ES5, especially for you, but the next question is: do I need ES6+ features when I work on React or Vue app (or basically on any JAvaScript app)? I don't need that, but I won't because it helps me write more efficiently, effectively, and with more fun (for sure!)

10 ES6 facets that you should know

1. JavaScript const and let

let vs. var

In ES6, you can declare a variable using the let keyword. The main difference between let and var is variables created by var are scoped to the function scope while variables declared by using the let keyword are scoped to the block scope.

On the other hand, a variable declared using var is hoisted (initialized with undefined before the code is run), but a variable declared by let syntax is not initialized until their definition is evaluated.

In addition, you can't re-declare a variable that was declared using let, while it's possible using var syntax.

1'use strict';
2var name = "Johny";
3var fooname= "Andrew"; // it works, 'Johny' is replaced with 'Andrew'.
5let age = 18; 
6let age = 22; // SyntaxError: Identifier 'age' has already been declared

Lastly, you cannot declare a global variable using let:

1var name = 'Johny'
2let age = 18
4console.log(window.name) // prints 'Johny'
5console.log(window.age // prints undefined

const syntax

In ES5, you use var to create a variable, and it does not matter it is variable or constant. In ES6+, It is possible to use the const keyword to declare variables. Constants resemble Let variables, but the value is not changeable.

1const name = 'Johny'
2name = 'Andrew' // Uncaught TypeError: Assignment to constant variable.

2. JavaScript promises

A promise is an object that represents the result of the asynchronous operation (success or failure)

A promise can have three states:

  • pending - operation is in progress

  • fulfilled - operation is done (success)

  • rejected - operation failed

In ES6, you can create promises like this:

1const myPromise = new Promise((resolve, reject) => {
2  setTimeout(() => {
3    resolve('done');
4  }, 500);

ES6 also provides a new way to handle promises called async/await. Take a look:

1const getData = async () => {
2  const data = await fetch(...);
4  return data;

Remember that the async function always returns a promise, even if the function does not return a promise. JavaScript will convert the returned value to promise then.

3. Rest and Spread Operations

Rest parameter

Rest operator allows you to expand a single variable into more. Rest parameter allows representing several arguments as an array. Take a look at this code:

1function multipleAll(a, b) {
2  return a * b;
5console.log(multipleAll(2,2)); // 4

The multipleAll function multiples arguments and return the results. Nothing surprising, but what in the case when we want to pass more arguments to a function, like this:


Thanks to the rest parameters, we can refactor the multipleAll function:

1function multipleAll(...args) {
2  let result = 1;
4  for (let arg of args) {
5    result = result * arg;
6  }
8  return result
10console.log(multipleAll(2,2)); // 4
11console.log(multipleAll(2,2,2)); // 8
12console.log(multipleAll(2,2,2,2)); // 16
13console.log(multipleAll(2,2,2,2,2)); // 32
14console.log(multipleAll(2,2,2,2,2,2)); // 64
15console.log(multipleAll(2,2,2,2,2,2,2)); // 128
16console.log(multipleAll(153,14,67,89,456,123456)) // 719053691360256 ;-) 

Spread operator

Spread syntax (...) allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

Take a look at the example:

1const human = {
2  name: 'Johny',
3  skills: ['writing', 'reading']
6const programmer = {
7  name: 'Andew',
8  age: 30,
9  skills: ['coding']
12const humanAndProgrammer = {
13  ...human,
14  ...programmer,
15  skills: [
16    ...human.skills,
17    ...programmer.skills
18  ]
21console.log(humanAndProgrammer) // prints:
22// [object Object] {
23//   age: 30,
24//   name: "Andew",
25//   skills: ["writing", "reading", "coding"]
26// }

In terms of using an array, you can also use the spread operator:

1const array1 = [1,2];
2const array2 = [3,4]
4const array3 = [
5   ...array1,
6   ...array2

4. Template literals

Template literals are text blocks defined by backticks (`) (instead of single or double quotes), and they have one significant advantage compared to strings. You can embed JavaScript expressions inside them:

1const name = 'Johny';
2const grreeting = `Hello ${name}`;

It's pretty helpful and much better than writing string like this:

1const name = 'Johny';
2const grreeting = 'Hello' + name;

This example is easy, but template strings are practical when you have something more sophisticated.

For example, literal templates support multiline templates. This is still valid:

2I am a multiline
5// Result:
6// "Hello,
7// I am a multiline
8// template"

5. Destructuring

The destructuring syntax is also pretty easy to understand and start using syntax. It allows unpacking variables from objects and arrays:

1const person = {
2  name: 'Johny',
3  age: 30
6const { age, name } = person
8console.log(age, name);
9// 30
10// "Johny

The example above shows how to destruct variables from the object. To do so, you need to use {} and names of variables that you want to destruct.

In addition, you can destruct values from arrays:

1const array = [10,100];
2const [ ten, houndret ] = array;
4console.log(ten, houndret);

6. Default function parameters

In ES6, you can initialize named parameters of function by default values. JavaScript will initialize those parameters when no value or undefined is passed to the function.

1console.log(greeting('Marcin')); // Marcin
2console.log(greeting()) // Johny

7. Arrow functions

Arrow functions are one of my favorites because they simplify using functions in JS. Before, there were mistakes with the 'this' keyword in functions because, in ES5, the function's scope was established based on where the function was called.

Do you remember functions like call, apply, and bind? Those don't work with the arrow function because arrow functions initialize scope based on the arrow function's scope.

Let's take a look t the example function foo:

1const foo = function () {
2  return 'bar'

Let's convert it to an arrow function. To do so, first, remove the "function" keyword

1const foo = () {
2   return 'bar';

Second, place an arrow between the () and opening body bracket

1const foo = () => {
2   return 'bar';

This is a proper arrow function, but we can still simplify it. We can remove body brackets and remove return - it will be insinuated

1const foo = () => 'bar';

Here you can see more arrow functions' examples: https://gist.github.com/Frodigo/72152ac9fac82531df466cfe44d331da

8. Object literal shorthand

This is pretty fun. Do you do something like this in your code?

1const name = 'Johny';
2const age = 30
4const man = {
5  name: name,
6  age: age

Once you use ES6+, you don't have to duplicate variable names from object properties thanks to object literal shorthand:

1const name = 'Johny';
2const age = 30
4const man = {
5  name,
6  age


in ES6+, you can import/export functionality from files and create reusable components in your app. Let's take a look at a typical example from react app:

1// MyComponent.js
2export const MyComponent = () => {
3  return <h1>This is my component</h1>
6export default MyComponent;

To import this component in another file, you can use two ways. The first is to use the default exported value or the named value.

2import MyComponent from './MyComponent' // using default exported value
3 // or 
5import { MyComponent } from './MyComponent' // used named exported value

10. The For/Of Loop

Looping in JS has been evaluated starting from the for a loop. Next was the forEach loop, and now we have a for...of the loop. Basic example:

1const array = [1,2,3,4,5]
3for (const element of array) {
4  console.log(element);

The one ES6feature that you won't use in a web project

At the and I would like to show you something quite popular, but it's not practical when you work with React or Vue apps.

JavaScript classes and inheritance

Oh yeah, I remember that moment everyone was excited because we had classes in JavaScript. After a few years, we won't use classes because frameworks that we work with use another approach (hooks and composables).

Note: classes are helpful in other cases. I only mean that you don't need them on the front end in typical apps (React and Vue)


So I hope you're more apparent on ES6+ features, and you will start using them if you haven't already used those. I showed your basics, and now you can dive into my other articles about react and using new knowledge on the battlefield ;)

Share this article with your friends!

Each share supports and motivates me to create new content. Thank you!

About the author

Marcin Kwiatkowski

Frontend developer, Certified Magento Full Stack Developer, writer, based in Poland. He has eight years of professional Software engineering experience. Privately, husband and father. He likes reading books, drawing, and walking through mountains.

Read more