Useful New Features in ES2016 and 2017 That You May Have Missed
Tags: javascript, oop, webdev
Published: 2020-01-04 21:21:03

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

ES2015 introduced lots of features, like arrow functions, class syntax for object creation and inheritance, `let` and `const`, and many other new features. In the next few years, more great features will be introduced into the language and the standard library. ES2016 was a minor revision with new features, such as introducing the `includes` function to arrays and the exponential operator. ES2017 introduced more features like `Object.values` and `Object.entries` and string functions like `padStart` and `padEnd`, and `async` and `await`. These are handy features that bring even more convenience to JavaScript developers, making JavaScript app development even easier.

* * *

ES2016 Features
===============

Array.includes
--------------

`Array.includes` checks if an item exists in an array. It takes a number or string, which the function can compare as the first argument and the index to search from as the second argument. The second argument can be positive or negative.

```javascript
const array = [1,2,3];  
const includesTwo = array.includes(2); // returns true
```

We can also search the array starting with a negative index, then the function search beginning from the computed index, which is the length of the array plus the second argument. So if we write:

```javascript
array.includes(2, -2);
```

Then the `includes` function will search starting with index `3 +(-2).` This means that `array.includes(2, -2);` should return `true`. If the absolute number of what you pass in is bigger than the length, then the whole array is searched.

The `includes` function was also added to TypedArray types like [Int8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array) , or [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) .

Exponential operator
--------------------

The exponential operator is another new feature of ES2016. The exponential operator is denoted by `**`. It’s the new syntax for computing exponential values, which is the alternative to the `Math.pow` function. For example, to compute 2 to the power of 3, we can write,

```javascript
2**3
```

which is 8. Note that in JavaScript, it’s impossible to write ambiguous expressions when we combine the exponential operator with unary operators like `-`, so something like `-2**2` is invalid in JavaScript. However, `-(2**2)` is valid since it’s unambiguous in that we know that the value is -4 since the exponential is in parentheses and the negative sign is outside.

We can force the base of the exponentiation expression to be a negative number by writing:

```javascript
(-2)**2
```

So this means the `base` has to be in parentheses.

* * *

ES2017 Features
===============

Object.values
-------------

The `Object.values` lets us get an array with the values of an object in an array. The values are returned in the same order as it is provided by the `for...in` loop, except that `Object.values` do not return values that are in the prototype chain.

For example, we can write:

```javascript
const obj = { a: 1, b: 2 };  
console.log(Object.values(obj)); // [1, 2]  
  
const obj = { 0: 'd', 1: 'e', 2: 'f' };  
console.log(Object.values(obj)); // ['d', 'e', 'f']  
  
const obj2 = { 100: 'd', 2: 'e', 7: 'f' };  
console.log(Object.values(obj2)); // ['e', 'f', 'd']  
  
console.log(Object.values('abc')); // ['a', 'b', 'c']
```

As we can see, `Object.values` works with objects and strings. If the keys are numbers, then they are returned in with the keys in increasing order, like in the `obj2` example above. For strings, it returns an array of the individual characters of the string.

**Object.entries()**
--------------------

The `Object.entries` function returns an array with each entry being the key-value pairs in their individual arrays. The entries are returned in the same order as it is provided by the `for...in` loop, except that `Object.values` do not return values that are in the prototype chain. As with any object, we can sort the array to get the entries in the order we want with the `sort` function.

For example, we can write:

```javascript
const obj = { foo: 1, bar: 2 };  
console.log(Object.entries(obj)); // [ ['foo', 1], ['bar', 2] ]  
  
const obj = { 0: 'x', 1: 'y', 2: 'z' };  
console.log(Object.entries(obj)); // [ ['0', 'x'], ['1', 'y'], ['2', 'z'] ]  
  
const obj2 = { 100: 'x', 2: 'y', 7: 'z' };  
console.log(Object.entries(obj2)); // [ ['2', 'x'], ['7', 'y'], ['100', 'z'] ]  
  
console.log(Object.entries('abc')); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]  
  
console.log(Object.entries(100)); // [ ]  
  
const obj = { a: 1, b: 2, c: 3};  
for (const [key, value] of Object.entries(obj)) {  
  console.log(`${key} ${value}`); // "a 1", "b 2", "c 3"  
}  
  
Object.entries(obj).forEach(([key, value]) => {  
  console.log(`${key} ${value}`); // "a 1", "b 2", "c 3"  
});
```

In the above examples, we can see that `Object.entries` return an array of key-value pairs with each entry as an array with the key being the first element and the value being the second element. If the keys are integers, then they are sorted in ascending numerical order. So `Object.entries(obj2)` returns `[ ['2', 'x'], ['7', 'y'], ['100', 'z'] ]`. It also works with strings with the individual characters return with the index of the characters as the key, so the key is the index of the string, which is the first element of each entry, and the individual character is the value of the string, which is returned as the second character. For objects that have no properties, like numbers and booleans, `Object.entries` returns an empty array.

The array returned by `Object.entries` can be converted to a `Map` object. It can be used like in the following example:

```javascript
const obj = { a: 1, b: 2 };   
const map = new Map(Object.entries(obj));  
console.log(map); // Map { a: 1, b: 2 }
```

String.padStart()
-----------------

The `padStart()` function adds a string the number of times before a string until it reaches the length that you specify. The function takes two parameters. The first is the target length of your string. If the target length is less than the length of your string, then the string is returned as-is. The second parameter is the string that you want to add the padding with. It’s an optional parameter and it defaults to `' '` is nothing is specified.

For example, we can write the following:

```javascript
'def'.padStart(10);         // "       def"  
'def'.padStart(10, "123");  // "1231231def"  
'def'.padStart(6,"123465"); // "abcdef"  
'def'.padStart(8, "0");     // "00000def"  
'def'.padStart(1);          // "def"
```

Note that each string is filled up to the target length with the string in the second argument. The whole string in the second argument may not always be included. Only the part that lets the function fill the string up to the target length is included.

String.padEnd()
---------------

The `padEnd()` function adds a string the number of times after a string until it reaches the length that you specify. The function takes 2 parameters. The first is the target length of your string. If the target length is less than the length of your string, then the string is returned as is. The second parameter is the string that you want to add the padding with. It’s an optional parameter, and it defaults to `' '` is nothing is specified.

For example, we can write the following:

```javascript
'def'.padEnd(10);         // "def       "  
'def'.padEnd(10, "123");  // "def1231231"  
'def'.padEnd(6,"123465"); // "defabc"  
'def'.padEnd(8, "0");     // "def00000"  
'def'.padEnd(1);          // "def"
```

**Object.getOwnPropertyDescriptors()**
--------------------------------------

The `Object.getOwnPropertyDescriptors()` function returns all the property descriptors of an object.

For example, we can use it like the following code:

```javascript
const obj = {  
  a: 1  
};const descriptors = Object.getOwnPropertyDescriptors(obj);
```

The `descriptors` object should have:

```javascript
{  
  a: {  
    configurable: true,  
    enumerable: true,  
    value: 1,  
    writable: true  
  }  
}
```

Async and Await
---------------

With `async` and `await`, we can shorten promise code. Before `async` and `await`, we have to use the `then` function, we make to put callback functions as an argument of all of our `then` functions. This makes the code long is we have lots of promises. Instead, we can use the `async` and `await` syntax to replace the `then` and its associated callbacks as follows. For example, we have the code to make requests to the back end with the Fetch API:

```javascript
const APIURL = "http://localhost:3000";
const subscribe = async data => {  
  const response = await fetch(`${APIURL}/subscribers`, {  
    method: "POST",  
    mode: "cors",  
    cache: "no-cache",  
    headers: {  
      "Content-Type": "application/json"  
    },  
    body: JSON.stringify(data)  
  });  
  return response.json();  
};

window.onload = () => {  
  nameForm.method = "post";  
  nameForm.target = "_blank";  
  nameForm.action = "";  
  nameForm.addEventListener("submit", async e => {  
    e.preventDefault();  
    const firstName = document.getElementById("firstName").value;  
    const lastName = document.getElementById("lastName").value;  
    const email = document.getElementById("email").value;  
    let errors = [];  
    if (!firstName) {  
      errors.push("First name is required.");  
    } 

    if (!lastName) {  
      errors.push("Last name is required.");  
    } 

    if (!email) {  
      errors.push("Email is required.");  
    } 

    if (!/\[^@\]+@\[^\.\]+\..+/.test(email)) {  
      errors.push("Email is invalid.");  
    } 

    if (errors.length > 0) {  
      alert(errors.join(" "));  
      return;  
    }  
    try {  
      const response = await subscribe({  
        firstName,  
        lastName,  
        email  
      });  
      alert(`${response.firstName} ${response.lastName} has subscribed`);  
    } 
    catch (error) {  
      alert(error.toString());  
    }  
  });  
};
```

We replaced the `then` and callbacks with `await`. Then we can assign the resolved values of each promise as variables. Note that if we use `await` for our promise code then we have to put `async` in the function signature as we did in the above example. To catch errors, instead of chaining the `catch` function in the end, we use the `catch` clause to do it instead. Also, instead of chaining the `finally` function at the bottom to run code when a promise ends, we use the `finally` clause after the `catch` clause to do that instead.

In the code above, we got the resolved value of the promise assigned to a variable instead of getting the value in the callback of the `then` function, like in the `const response = await subscribe({...})` line above.

`async` functions always return promises and cannot return anything else like any other function that uses promises. In the example above, we used the promised based Fetch API and `async` and `await` syntax, we showed that we can chain promises in a much shorter way than with the `then` function with callbacks passed in as an argument.

ES2016 and 2017 gave us convenient features that enhance the already great syntactic sugar and functions that were added to ES2015, which was a significant improvement over its predecessor. These two versions of JavaScript make JavaScript development even better with new Object, string, and Array methods and shorthand for chaining promises.