Top 6 ES6 Fundamentals You Need to Know
Tags: javascript, es6, web, frontend
Published: 2021-06-04 04:43:30

---
title: Top 6 ES6 Fundamentals You Need to Know
published: true
description: ES6 fundamentals that you need to master to create modern, structured and readable code
tags: javascript, es6, web, frontend
cover_image: https://images.unsplash.com/photo-1558979533-d390b1897d5c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1500&q=80
---

**Table Of Contents**
* [What is ES6?](#what-is-es6)
* [1. Let and Const](#let-const)
* [2. Arrow Functions](#arrow-functions)
* [3. Template Literals](#template-literals)
* [4. Default Parameters](#default-parameters)
* [5. Rest Parameters and Spread Syntax](#rest-spread)
* [6. Destructuring Assignment](#destructuring-assignment)
* [Bonus: Promise](#bonus-promise)

## What is ES6? <a name="what-is-es6"></a>
ES6 or ECMAScript 6 was the second major revision to Javascript, which enable us to write less and do more. It has a lot of new features and new syntaxes to make your code looks more modern, more structured and more readable.

On this article, we will cover several ES6 fundamentals that you need to master to get you ready with Modern Javascript. Let's dive in!

## 1. Let and Const <a name="let-const"></a>
`let`: mutable variables, means we can reassign its value. `let` can be declared without being initialized.

`const`: immutable variables, means we cannot reassign value to `const` variables. `const` must be initialized during declaration.

Both of them are block-scope variables, which means it is only available within the block where the variable is declared.

### Takeaways
It is recommended to use `let` and `const` than using `var`, because when we use `let` and `const` will be hoisted to the top but they are not initialized (unlike `var` that has been initialized with the value of `undefined`) and this helps us to get better error message. Furthermore, we can't iniatialized those variables before we declare them. This is useful to make sure that our variables has been declared before we can use them and this is a good practice in programming.

#### Code Examples:
```javascript
// traditional
var x = 5;
y = 8;
var y;

console.log(x); // 5
console.log(y); // 8

// es6
let i = 10;
j = 15;
let j;
console.log(i); //10
console.log(j); // Error: Cannot access 'j' before initialization

const k = 29;
k = 39;
console.log(k); // Error: Assignment to constant variable.

let m;
m = 'hello';

const n;
n = 'goodbye';
console.log(m); // hello
console.log(n); // Error: Missing initializer in const declaration
```


## 2. Arrow Functions <a name="arrow-functions"></a>
Let's begin by showing you how to write function in traditional syntax vs ES6 syntax.
```javascript
// traditional
var sum = function (a, b) {
  return a + b;
}

// es6
const sum = (a, b) => a + b;
```

It's really awesome, right?
The arrow function makes your code looks clean, more structured and more readable.

When the body inside arrow function has more than one line, we need to wrap it inside `{}`.
```javascript
const sum = (a, b) => {
  const result = a + b;
  return result;
}
```
Arrow function commonly used as callbacks. You will find it a lot when working with `map()`, `filter()` and `reduce()`.

```javascript
// traditional
const arr1 = [1,3,5];
const square1 = arr1.map(function(item) {
  return item ** 2;
});
console.log(square1); // [1, 9, 25]


// es6
const arr2 = [1,3,5];
const square2 = arr2.map(item => item ** 2);
console.log(square2);
```

Although it is a powerful addition in ES6 but there are limitations that we need to understand to avoid errors that are difficult to track, such as when using `this` inside arrow function.

On the `car2` example, the result might be something that you are not looking for. So, we need to be careful when using arrow function. This happens because arrow function doesn’t have its own bindings to `this`, instead they *inherit from parent scope*, which is called **lexical scoping**.

```javascript
// with regular function
const car1 = {
  brand: 'Toyota',
  showBrand: function() {
    console.log(this.brand);
  }
}
car1.showBrand(); // 'Toyota'


// with arrow function
const car2 = {
  brand: 'Mazda',
  showBrand: () => console.log(this.brand)
}
car2.showBrand(); // undefined
```


## 3. Template Literals <a name="template-literals"></a>
Template literals or template strings is a new way to concatenate strings in ES6.
Let's take a look at code example below.

This is how we create greetings function that will greet the given name in traditional syntax.
```javascript
// traditional
var greetings = function (name) {
  return 'Hello ' +  name;
};
console.log(greetings('Bambang')); // 'hello Bambang'
```

Now, let's refactor to template literals!
```javascript
// es6
const greetings = (name) => `hello ${name}`;
console.log(greetings('Bambang')); // 'hello Bambang'
```

With template literals, our code looks more structured. We don't need the `+` sign anymore and we can use `${}` to call variables.


## 4. Default Parameters <a name="default-parameters"></a>
In ES6, we can give default value to function's parameters.

With the old syntax, this is how we create default value to a parameter.
```javascript
// traditional
var sayGoodbye = function (name) {
  name = name !== undefined ? name : ‘Lorem Ipsum’;
  return `Bye bye ${name}`
}
```

Now, let's refactor using ES6 default parameter!
```javascript
// es6
const sayGoodbye = (name = ‘Lorem Ipsum’ ) => `Bye bye ${name}`
console.log(sayGoodbye()); // Bye bye Lorem Ipsum
console.log(sayGoodbye(‘Bambang’)); // Bye bye Bambang
```

It's so simple and easy to understand. This also helps you to handle error in advance when you forget to assign the parameter.


## 5. Rest Parameters and Spread Syntax <a name="rest-spread"></a>
Previously, before we have rest parameter, we can code like this to convert arguments to array. However, it only supports limited number of arguments and you need to be sure how many items are there.

```javascript
// traditional
var cities = function(city1, city2, city3, city4, city5) {
  var citiesToArray = Array.from(arguments);
  return citiesToArray;
}
console.log(cities('tokyo', 'singapore', 'jakarta', 'moscow', 'frankfurt')); // ['tokyo', 'singapore', 'jakarta', 'moscow', 'frankfurt']
```

But now, thanks to ES6 which introduces us to Rest parameter.

Rest parameter accepts unlimited arguments and returns it as array. You can use rest parameter by adding three dots `...`. When you use rest paramater as argument inside a function, it must be at the end.

```javascript
// es6
const cities = (city1, city2, ...others) => {
  console.log(city1); // 'tokyo'
  console.log(city2); // 'singapore'
  console.log(others); // ['jakarta', 'moscow', 'frankfurt']
}
cities('tokyo', 'singapore', 'jakarta', 'moscow', 'frankfurt');
```
Because it turns our parameters into an array, we can combine it with `map()` just like the example below.

```javascript
const doubleTheNumbers = (...args) => args.map(item => item * 2)
console.log(doubleTheNumbers(3,5,20)); // [6, 10, 40]
```



Next we have spread syntax `...`, which looks exactly the same as rest parameter.
However, spread syntax does quite the opposite of rest parameter. With spread syntax we can get list of arguments from array.


For example, let's say we have an array and we want to find the lowest number. Here's how we can do that with spread syntax.
```javascript
const arr = [6, 5, 8, 2, 9];
console.log(Math.min(...arr)); // 2
```

Besides that, we can easily push elements into array using spread syntax. Without spread syntax, it would be something like this, which might be not what we are looking for..
```javascript
// traditional
const fruit1 = ['apple', 'mango'];
const fruit2 = ['strawberry', 'grape', 'melon'];
fruit1.push(fruit2)
console.log(fruit1); // ["apple", "mango", Array ["strawberry", "grape", "melon"]]
```
Now, let's refactor with spread syntax!
```javascript
// es6
const fruit1 = ['apple', 'mango'];
const fruit2 = ['strawberry', 'grape', 'melon'];
fruit1.push(...fruit2);
console.log(fruit1); // ["apple", "mango", "strawberry", "grape", "melon"]
```

We can copy an array using spread syntax too!
```javascript
// copy array
let nums = [3, 7, 5, 6];
let copyNums = [...nums];
copyNums.push(9);
console.log(nums); // [3, 7, 5, 6]
console.log(copyNums); // [3, 7, 5, 6, 9]
```

Both rest parameter and spread syntax are really useful, powerful and easy to understand!



## 6. Destructuring Assignment <a name="destructuring-assignment"></a>
Destructuring assignment allows us to unpack values from array and properties from object into variables.

### Array
This is how we destructure an array into variables.
```javascript
const menu = ['chicken', 'beef'];
const [menu1, menu2] = menu;

console.log(menu1); // chicken
console.log(menu2); // beef
```

We can also use destructuring assignment to swap between two values in array.

Here's how we swap array using traditional syntax.
```javascript
// traditional
var swap = function() {
  var arr = [1,2];
  var temp;
  temp = arr[0];
  arr[0] = arr[1];
  arr[1] = temp;

  return arr;
}
console.log(swap()); // [2,1]
```

And now, let's refactor the code using destructuring assignment!
```javascript
//es6
let [a,b] = [1, 2];
[b,a] = [a,b];
console.log(a, b); // [2,1]
```

We have less code and it's easier to understand, isn't it?



### Object
We can also use destructuring assignment with object. Take a look at the example below.

Here's how we do it with traditional syntax to get the object's value.
```javascript
// traditional
var car = {
  model: 'Toyota',
  year: 2015,
  colors: ['black', 'blue', 'yellow']
}

var model = car.model;
var year = car.year;
var colors = car.colors;

console.log(model);
console.log(year);
console.log(colors);
```

Now let's refactor with destructuring assignment!
```javascript
// es6
const car = {
  model: 'Toyota',
  year: 2015,
  colors: ['black', 'blue', 'yellow']
}

let {model, year, colors} = car;
console.log(model);
console.log(year);
console.log(colors);
```
There's a lot more you can do with destructuring assignment as it is really useful and practical, especially when you are working with modern Javascript.

## Bonus: Promise <a name="bonus-promise"></a>
In Javascript, Promise means doing something that takes time then produces a result, just like real-world promise.

After a Promise takes the time needed to produce the promised result, it will either **resolve** when it’s fulfilled or **reject** when there is an error. If it’s resolved, we can get access to the returned data and if it’s rejected, we can throw an error.

In this example, we want to create a network request from API that returns either a resolved Promise when it's succeed or a rejected Promise when we couldn't get the data.

```javascript
const getTodo = (resource) => {
  return new Promise((resolve, reject) => {
    const request = new XMLHttpRequest();

    request.addEventListener("readystatechange", () => {
      if (request.readyState === 4 && request.status === 200) {
        const data = JSON.parse(request.responseText);
        resolve(data);
      } else if (request.readyState === 4) {
        reject("error getting resource");
      }
    });

    request.open("GET", resource);
    request.send();
  });
};

getTodo("https://jsonplaceholder.typicode.com/todos/1")
  .then(data => {
    console.log("promise resolved:", data);
  }).catch(err => {
    console.log("promise rejected:", err)
  });
```

Promise is a part of Asynchronous Javascript, a technique that allows us to create an action that we start now and finish later, which means we can let our code do several things without blocking the main thread.

If you want to learn more on Asynchronous Javascript, you can head over to my [Async/await post](https://es6-notes.vercel.app/posts/async-await?utm_source=dev.to&utm_medium=article).

---

Thanks for reading!

Would really appreciate if you could share your thoughts and feedbacks in the comment ✨