Features I Wish I’d Known About ES6 & ES7
Tags: javascript, webdev
Published: 2020-07-02 08:42:23

# Features I Wish I’d Known About ES6 & ES7

Many people consider JavaScript as the heart of dynamic web applications. and since it was created in 1997 by [Brendan Eich](https://en.wikipedia.org/wiki/Brendan_Eich). Over years especially after the EcmaScript standard JavaScript had severe and powerful changes including adding new features and fixing bugs or enhancing undesired behavior. In this article we will explore the new features added to JavaScript ES6 and ES7.


## Historical Background 

Oh wait a minute! What is ES6 and Who is responsible for developing and improving Javascript ?

### Ecma and EcmaScript

As we mentioned earlier Javascript was originally created to live in the browser and make users life easier providing better user experience. After that **Microsoft** created its flavor of JavaScript to be used in their browser Internet Explorer.Thus, We needed a way to standardize the javaScript language and here **[Ecma International](https://en.wikipedia.org/wiki/Ecma_International)** comes.

Ecma international is a standards organization that is responsible for making JavaScript specification and this specification is "EcmaScript". And in practice , the term “ javaScript” and “EcmaScript” are used  interchangeably. 

## So What’s new ?

Now , let’s explore some of the most important and commonly used ES6 and ES7 features.

*   Let and Const
*   Arrow Functions
*   Default parameters
*   Destruction assignment
*   Class keyword
*   Generators
*   Promises
*   Array.prototype.includes (ES7)
*   Exponential operator (ES7)

## Scopes and variables declaration (let & const) 

Scope is  where our variables live and are accessible in. Before ES6 JavaScript had only two types of scopes.



*   **Global scope**  " when we declare variables outside functions."
*   **Function scope**

 ```js
var x = 1;                                     // global Scope

function myFunction() {
    var x = 2;
    console.log("Inside function x is ", x);   // Function Scope
}

myFunction();                                 // Result : Inside function x is 2
console.log("In global scope x is ", x);      // Result : In global scope x is 1
```



In the previous example  when we invoke the function (myFunction) we get x = 2 while in global x = 1 . because we have two different values of x depending on the scope of the variable.

Now, let's try another example:


```js
var index = 5
for (var index = 0; index < 10; index++) {
    // Do some tasks
}
console.log(index);                          // Result : 10
```


This seems odd as we would expect index = 5 as we see in the previous example but instead we got 10 ! \
As we mentioned earlier that we have only two types of scopes. So when we declare something like counter in _for loop_ it is still in the _global scope_ and that’s why we had this unexpected result.

### Let and const keywords

EcmaScript2015 or ES6 introduced new keywords `let` and `const` to declare variables and fix  `var` problems. As these new keywords are block-scoped (a block is anything between { } ). 

Let’s try the previous example using `let`  


```js
let index = 5;
for (let index = 0; index < 10; index++) {
    // Do some tasks
}
console.log(index);                       // Result : 5
```


Now we got index = 5 as expected as let inside the for loop ( blocked between { }) has nothing to do with let in the global scope.

Another useful keyword is `const` as it allows us to declare constant values (not meant to be changed).

`const` is also block-scoped same as `let` but the main difference between them is that const value can't be changed after assigning variable to a value.


```js
const PI = 3.141592653589793;
PI = 3.14;   // this line will cause a TypeError
```


#### Note

Re-assigning variables with `const` keyword will cause error only if we assign a primitive value. But if we declare an object we can add new methods and properties to it. That is because when we declare a new object with const keyword we don’t store the whole object in the variable like primitive values instead we store a reference to this object. So it will cause an error only if we tried to change the reference to another object. 

Now, let's see an example:


```js
const obj1 = { name: "John Doe" };
obj1.age = 40;  // this is totally fine and age property will be added to obj1
console.log(obj1.age);   // result : 40
obj1 = { name: "Foo" };  // will cause a TypeError as we are changing the
```


## Arrow Function 

ES5 function statement:


```js
const sumTwoNumbers = function (num1, num2) {
    return num1 + num2;
}
```


ES6 provides new elegant and shorter syntax  for function statements called _Arrow function._


```js
const sumTwoNumbers = (num1, num2) => { return num1 + num2; }
```


And this could be shorter though, If the function has only one statement and returns a value we can remove the `return` keyword and the curly brackets. And this will give the same result as the previous example.


```js
const sumTwoNumbers = (num1, num2) => num1 + num2;
```


In case we have only have one parameter we can remove the parentheses 


```js
const multiplyBy10 = num => num * 10;
```


### Arrow Function and `this`

Arrow functions handle `this` in a  different way from regular functions. In regular functions `this` keyword represented the object that called the function (the executer), which could be the window, the document, or whatever. While in the _Arrow function_ `this` represents the object that defined the arrow function.

In short , in arrow function `this` represents the definition context while in regular function `this` represents the execution context.

Now let’s take a look at a couple of examples two show the difference between each of them:


```js
function myFunction() {
    console.log(this);
}

const myArrowFunction = () => console.log(this);

myFunction();      // this =  the Window object "The global object";
myArrowFunction(); // this =  the Window object "The global object";
```


In this example both of the regular and arrow functions give the same thing and `this` refers to the global object. In the case of a browser the global object is _Window._

But there is a big difference between them although they gave the same result. In _regular function_ `this` is the **Window** object because the executor of the function is the global object aka **Window**. While in the _Arrow function_ case `this` is the Window because the arrow function was defined in the global scope.

Now let’s take another example to demonstrate this:

We have _html_ file with javascript file imported in it and a simple button


```js
<!DOCTYPE html>
<html lang="en">
.
.
.
<body>
    <button id="btn">click</button>
    <script src="./index.js"></script>
</body>

</html>
```


**In index.js**


```js
function fn() {
    console.log(this);
}

const btnElement = document.getElementById('btn');

btnElement.addEventListener('click', fn);
```


When clicking the button we will got this printed to the console and this will be:


```js
<button id="btn">click</button> 
```


Now let’s change **_fn_** function to an Arrow function and try again.


```js
const fn = () => console.log(this);
const btnElement = document.getElementById('btn');

btnElement.addEventListener('click', fn);
```


When clicking the button we will get this printed to the console and this will be the **_Window object._**

### Explanation 

In **regular function** this gets its meaning during runtime and refers to the object that executes it and this is the btnElement in our case.

In **arrow function** this gets its meaning from the definition context which is the global object and that’s why we get the Window object.

## Default parameters

Another cool thing in the ES6 that default argument. If you are familiar with other programming languages you probably know what the default parameter is.

In short , it means that you can initialize a parameter with a default value if no value is passed when invoking the function. Let’s see an example to handle this **before** _ES6._


```js
// ES5 style for default parameters
function add(a, b) {
    var b = (typeof b !== 'undefined') ? b : 5
    return a + b
}
add(3, 4);    // result = 7      
add(1)       // result = 6
```


In the previous example we introduced _ES5_ technique for handling default parameters. As we know javascript initializes parameters with “undefined” at first. So we check if parameter b is undefined this means that he had no value in the invoking line and then we assign a default value ( b = 5).

Now let’s see the new _ES6_ way for handling the same situation:


```js
function add(a, b = 5) {
    return a + b
}

add(3, 4);    // result = 7      
add(1)       // result = 6
```


This is very simple and straightforward syntax. 

## Note

Keep in mind to keep all default parameters to the right otherwise you won’t get the proper result.


```js
// Don't do this 
function add(a = 4, b) {
    return a + b
}

add(1)       // result = NaN

// the right way 
function add(a, b = 4) {
    return a + b
}
add(1)       // result = 5
```


## Destruction assignment

Destruction is unpacking properties from objects or array elements into distinct separate variables. Lets first explore array destruction.


```js
let colors = ['one', 'two', 'three']

let [red, blue, yellow] = colors

console.log(red);      // one
console.log(blue);     // two 
console.log(yellow);   // three
```


In the previous example we first declared an array (**_colors_**) and then using _destruction_ we extracted elements from this array into separate variables. The first variable “red” will match the first element in the array and so on.

This is a very simple and elegant way to extract variables from an array into separate variables.

### Swapping values

Let’s try this approach to swap variables:


```js
let a = 5;
let b = 10;

[a, b] = [b, a]

console.log(a);   // a = 10
console.log(b);   // b = 5
```


Now, let’s see object destruction:


```js
const user = {
    id: 1,
    name: "Ali",
    age: "30"
}

// lets extract the user name only
const { name } = user

console.log(name);  // Ali
```


Using destruction and default values


```js
const user = {
    id: 1,
    name: "Ali",
}

const { name, age = 55 } = user

console.log(age);  // 55
```


Object and array destruction is very handy and makes life easier especially when using it with extracting variables from an http request.

## Class keyword

ES6 added `class` keyword and unlike other traditional object-oriented supporting languages like java or c++ ,class keyword in Javascript is just a [Syntactic sugar](https://en.wikipedia.org/wiki/Syntactic_sugar#:~:text=In%20computer%20science%2C%20syntactic%20sugar,style%20that%20some%20may%20prefer.). And under the hood it’s just a special function. Let’s try it out.


```js
class abc {
    constructor(name, age) {
        this.name = name;
        this.age = age
    }
}

// ES5 same output
var abc = function abc(name, age) {
  this.name = name;
  this.age = age;
};
```


## Generators

In a regular function we return only one value when invoking the function (or nothing). But with this new ES6 features we will be able to return more than one value from a function. On at a time.to create a generator function we need a special syntax so Let’s see an example:


```js
function* numberGenerator() {
    yield 1;
    yield 2;
    return 3;
}

let generator = numberGenerator();

let one = generator.next();
let two = generator.next();
let last = generator.next();

console.log(one);    // { value: 1, done: false }
console.log(two);    // { value: 2, done: false }
console.log(last);   // { value: 3, done: true }
```


## Promises

JavaScript is a single-threaded language supporting synchronous and asynchronous operations. And promises are just a more elegant way to deal with these asynchronous tasks than callbacks. And a very handy way to avoid [callback hell](http://callbackhell.com/).

A promise is an object representing the result of asynchronous tasks which are tasks that don’t block the execution until it is finished. This approach is great for time consuming tasks.

Let’s see a simple example:


```js
let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("resolved!"), 1000);
});

// resolve runs the first function in .then
promise.then(
  result => alert(result), // shows "done!" after 1 second
  error => alert(error) // doesn't run
);
```


## Array.prototype.includes

Although ES6 had many features and things to discuss but also ES7 introduced new features. Array.prototype.includes is a replacement for indexOf we use to check the presence of a value in an array.as indexOf had weird behavior as it returns a number and in case the element is not in the array it returns -1 .So we had to perform another check using the return number from **_indexOf_**. On the other hand **_includes_** is straightforward and returns boolean. Let’s see an example comparing these two alternatives.


```js
let colors = ['red', 'white', 'black', 'blue']

// using indexOf 
console.log(colors.indexOf('red'));     // 0
console.log(colors.indexOf('purple'));  // -1

if (colors.indexOf('purple') === -1) {
    console.log("Not found");
}

// using includes 
console.log(colors.includes('red'));      // true
console.log(colors.includes('purple'));  // false

if (!colors.includes('purple')) {
    console.log("Not found");
}
```


## Exponential operator

Let’s test one last ES7 feature for this article. In ES6 and earlier JS when it comes to exponential operators we had to work around to get the result as there wasn't an explicit operator. Let’s see how we would do this in ES6 syntax.


```js
 let result = Math.pow(2, 3)

console.log(result)  // 8
```


We had to use the built-in method **_pow_** in **_Math_** object. Or we would make a function to get the same result. Now let’s see what it would be in ES7.


```js
let a = 2 ** 3
let b = 3 ** 3
console.log(a === Math.pow(2, 3)) // true
console.log(b === Math.pow(3, 3)) // true
```


Very simple and easy to read as we see in other languages like python for instance. 

## Conclusion

JavaScript is becoming more popular over the years and it’s community is growing rapidly. We tried to cover some of the important features that ES6 and ES7 added to JS but there are more and more to learn.