ES2020: New Features & What's Beyond
Tags: node, javascript, beginners, vanillajavascript
Published: 2021-11-26 17:19:27

The world of **JavaScript**( *officially* ECMAScript ) changes fast and with awesome features getting added each year, it's certainly hard to keep up. The last big overhaul happened in **ES2015** when a bunch of new features, sugarcoated syntax were added to the language.

ECMAScript community releases new features every year. In this post, we will have a look at **7** key features that were introduced in [ES2020](https://262.ecma-international.org/11.0/)


1. **Big Int **
2. **Nullish Coalescing Operator**
3. **Optional Chaining**
4. **Global this**
5. **Promise.allSettled**
6. **Dynamic Import**
7. **String.prototype.matchAll**

*Let's get into each one by one*


## 1. Big Int
___
`BigInt` is a special data type introduced in ES2020 to define numbers that exceed the `Number` data type range. The `Number` data type limits between -(2^53-1) to -(2^53-1), which we can check using
`Number.MAX_SAFE_INTEGER` & `Number.MIN_SAFE_INTEGER`.

```javascript
console.log(Number.MIN_SAFE_INTEGER);
// -9007199254740991

console.log(Number.MAX_SAFE_INTEGER);
// 9007199254740991
```

Introduction to `BigInt` now increases the total number of `primitive` data type to `8`, the rest being,
1. Undefined
2. Null
3. Number
4. String
5. Object
6. Symbol
7. Boolean


To use BigInt, we simply append `n` at the very end of an integer, and that would be parsed as a BigInt.


```javascript
BigInt("1")    // -> 1n
typeof(1n)    // -> "bigint"
```

### a) BigInt Uses :

BigInt is useful in situations where we have to essentially deal with large integers that are beyond the scope of `Number`  type.


```javascript
console.log(18014398509481982n + 18014398509481982n)  // -> 36028797018963964n
```

### b) BigInt Operations :

All arithmetic operations are valid, the only exception to this is `unary plus operator`
```javascript
console.log(1n + 1n)       // -> 2n
console.log(7n / 3n)      // -> 2n
console.log(+10n)	  // -> Unary Operator error
```


The same goes for comparison as well, however, strict equality doesn't hold when compared with the `Number` data type.

```javascript
10n == 10 -> True
10n === 10 -> False
```


## 2. Nullish Coalescing Operator
___
The Nullish Coalescing operator is not something new but rather a sugarcoated version of a pattern we have been doing for quite a long time.

Have a look at this piece of code :
```javascript
if (a !== null && a !== undefined){
  return a;
}
else {
  return b;
}

// Now, nullish coalescing operator would simplify the above logic to :
a ?? b

```

In simple terms,

_ `??` returns the first argument if it is defined i.e neither `null` nor `undefined` _

_ `??` returns the second argument if the first argument is either `null` or `undefined`  _



Confused? Well let's have a look at few examples to clear up things

```javascript
1 ?? 2 	// 1 (returns the first argument as its neither null nor undefined)

undefined ?? 1 	// 1 (returns the second argument as the first one is undefined)

// we can even chain up several arguments as well, and the operator would return the first `defined value`

var country = null;
var state = undefined;
var city = "London";

console.log(country ?? state ?? city) // London (returns the first `defined value`)

```
### Use case :

Let's say if a user is logged-in, display the first name else display "Anonymous" :

```javascript
When logged-in
let user = "Alice"
console.log(user ?? "Anonymous"); // Alice

When not logged-in
let user = undefined;
console.log(user ?? "Anonymous"); // Anonymous
```


## 3.  Optional Chaining
___
The Optional Chaining Operator introduced in ES2020 is similar to the `.` (dot operator). It solves a very specific problem and is useful when we need a property that is nested deep in an object.

Consider the example below :
```javascript
let response = {
	type : "customer",
	isSignedIn : true,
	details : {
		age : 22,
		name : "Lucy",
		Country : "Estonia"
	}
}
```
Given the above example is an API response and we aren't sure if the property we are accessing even exists inside the object or not, then traditionally we have to do something like below to make sure we don't have any `nullish` value when nesting inside the `response` object properties

```javascript
const data = response.details && response.details.name
```

However, with Optional Chaining, we can do :

```javascript
const data = response.details?.name
```
JavaScript makes sure at each level of the object the property is not nullish (null or undefined), hence proving `?.` much practical than plain ol' dot operator.

Gotchas with :
Optional Chaining throws an error on the left-hand side of an assignment.
The very first property before the `?.` must be defined and cannot be invalid.
Similar to `?.` we have slightly different variants too :

`?.[] => calling arrays`

`?.() => calling functions`


## 4. Global this
___
Think about the number of environments and platforms we run JavaScript in, browsers, smartphones, servers, robotics equipment.
 For each environment, the JavaScript Object model is different and the global object might point to a different property.

In browsers, the global object could be `window`, `self` or `frame`, depending on the context. However there is no scope of the above-mentioned properties in NodeJs, hence it uses `global` to point to its global object.

Can we see the chaos here? If we have to run our `js` code in a range of different environment we need to figure out its global object first and is exactly what we have been doing for so long.

A common pattern to figure out the global object is as :

```javascript
function getGlobalObject() {
  if (typeof globalThis !== 'undefined') { return globalThis; }
  if (typeof self !== 'undefined') { return self; }
  if (typeof window !== 'undefined') { return window; }
  if (typeof global !== 'undefined') { return global; }
  throw new Error('cannot find the global object');
};

if (typeof getGlobalObject().Promise.allSettled !== 'function') {
  // the Promise.allSettled() Not available in this environment
}

```
However, the above solution has its own limitations and trade-offs.

`globalThis` tries to address the issue by pointing `globalThis` keyword to its global object model irrespective of the environment(as it is available everywhere). It was introduced in 2020 and currently stands on stage 4 and is available on most browsers.

```javascript
// nodeJS
console.log(globalThis) // returns the global object
// browsers
console.log(globalThis) // returns the window object
// web-workers
console.log(globalThis) // returns the global web workers context

```
With the introduction of `globalThis`, it would be best practice to stop using `this` keyword in the context of global objects and start using `globalThis`  instead.


## 5. Promise.allSettled
___
`Promise.allSettled()` is a method that takes an iterable object(array) and returns a promise when all the provided promises have either resolved or rejected, meaning it does not short-circuit in the middle.

The returned outcome is an object with two things :

	_a) value -> If the status is fulfilled._

	_b) reason -> If the status is rejected._

It's hard not to talk about the ES2015's `Promise.all` and its similarities/dissimilarities with `allSettled`
A striking difference between these two would be `all` short-circuits in the middle if any of the provided promises is rejected, while `allSettled` waits for async result and filters them by status and never shortcircuits.

Let's have a look at its working :

```javascript
const promise1 = new Promise((resolve) => resolve("yay"));
const promise2 = new Promise((resolve, reject) => reject("oh-no"));
	
	 
	(async () => {
	 try {
	 const result = await Promise.allSettled([promise1, promise2]);
	 console.log(result);
	 } catch (error) {
	 console.error(error);
	 }
	 
	
	})();
 // Output:
 // [
 // { status: 'fulfilled', value: 'yay' },
 // { status: 'rejected', reason: 'oh-no' },
 // ]
```


If we compare it with `all` :

```javascript
const promise1 = new Promise((resolve) => resolve("yay"));
const promise2 = new Promise((resolve, reject) => reject("oh-no"));
	
	 
	(async () => {
	 try {
	 const result = await Promise.allSettled([promise1, promise2]);
	 console.log(result);
	 } catch (error) {
	 console.error(error);
	 }
	 })()

 // Output:
 // Error : "oh-no" 
```

## 6. Dynamic Import
___
The amount of JS heavy apps we ship these days can be quite overwhelming and with these lot of javascript files, the module import/export should be effective.

ES2020's dynamic import addresses this issue to make the page load ups, first meaningful paint etc efficient and fast.
This is done by dynamically importing the files that we need at that point in time.

The `import` keyword was introduced in `ES2015`, and we have been importing modules like 

```javascript
import React from 'react';
```

ES2020 allows us to use `import` as a function (although it looks like a function, it is not)


```javascript
// we dont need to set type of module below
<script>
  import('./add.js')
    .then(module => module.default(3, 7)) //returns 10
    .catch(error => // log error here);
</script>
```
The above piece of code makes sure the `add.js` module is only imported when we need to sum up two numbers. It doesn't unnecessarily bloat up the js code which could make page loads slow. 

## 7. String.prototype.matchAll
___
`matchAll` is a new method that is added to the string prototype. This returns an iterator matching against a regular expression that we have given.


A simple example to demonstrate the same :

```javascript
const test = "climbing, oranges, jumping, flying, carrot";

const regex = /([a-z]*)ing/g;

const matches = [...test.matchAll(regex)];

const result = matches.map(match => match[1]);

// outputs the following :
["climb", "jump", "fly"]
```

<br />
<br />


While we just finished learning **ES2020**, the **ES2021** has already been drafted for its next release. Here's what's in the box for us :


1. String.prototype.replaceAll
2. Promise.any
3. Logical Operators and Assignment Expressions
4. Numeric Separators
5. WeakRefs
6. Intl.ListFormat


**Some Important Resources that I have collected over time: **

i. [https://auth0.com/blog/javascript-whats-new-es2020/](https://auth0.com/blog/javascript-whats-new-es2020/)

ii. [https://www.martinmck.com/posts/es2020-everything-you-need-to-know/](https://www.martinmck.com/posts/es2020-everything-you-need-to-know/)

iii. [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator)

iv. [https://blog.tildeloop.com/posts/javascript-the-difference-between-match-and-matchall](https://blog.tildeloop.com/posts/javascript-the-difference-between-match-and-matchall)

_Loved this post? Have a suggestion or just want to say hi? Reach out to me on [Twitter](https://twitter.com/abhinavanshul03)_

Originally written by [Abhinav Anshul](https://javascript.works-hub.com/users/c49b5fad-2fef-4acc-aa7a-7cd78f11c9a1?utm_source=dev_to&utm_medium=blog_xpost) for [JavaScript Works](https://javascript.works-hub.com/learn/es2020-new-features-and-whats-beyond-157e2?utm_source=dev_to&utm_medium=blog_xpost)