What's new in ECMAScript 2020 (ES2020) - Biggest new features

What's new in ECMAScript 2020 (ES2020) - Biggest new features

There is some most awaited feature updates in JavaScript. In this article, we’re going to review some of the latest and greatest features coming with ES2020.

BigInt

BigInt is a new 7th primitive data type in JavaScript and arguably the biggest new addition of ES2020. It's meant to allow developers to work with some really big integers. The largest number JavaScript can handle is 2^53, which we can see with MAX_SAFE_INTEGER.

const max = Number.MAX_SAFE_INTEGER;

console.log(max); // 9007199254740991

when you go high enough things start to get wired. With BigInt, there are no limits - except for your device's memory. A BigInt is created by appending n to the end of an integer literal — 10n — or by calling the function BigInt().

const myBigNum = 200000000000000000000000000000n;

console.log(myBigNum * 2n); // 200000000000000000000000000000n

const hugeHexNum = BigInt("0x1fffffffffffff")
// ↪ 9007199254740991n

BigInt is similar to Number in some ways, but also differs in a few key matters — it cannot be used with methods in the built-in Math object and cannot be mixed with standard Number with BigInt numbers. Any math will need to be also done with BigInt.

Dynamic Import

if you had a file full of utility functions, some of them may rarely be used and importing all of their dependencies could just be a waste of resources. Now we can use async/await to dynamically import our dependencies when we need them.

script.js

const multiply = (num1, num2) => num1 * num2;

export { multiply };

index.js

const calculate = async (num1, num2) => {
  if (num1 && num2) {
    const math = await import('./script.js');
    console.log(math.multiply(2, 8));
  };
};

calculate(3, 6);

Private Class Variables

One of the main purposes of classes is to contain our code into more reusable modules. Because you’ll create a class that’s used in many different places you may not want everything inside it to be available globally. Now you can make private variables by just adding a simple hash symbol in front of our variable.

class Message {
  #message = "Hello JavaScript"

  greet() { console.log(this.#message) }
}

const greeting = new Message()

greeting.greet() // Hello JavaScript
console.log(greeting.#message) // Private name #message is not defined

Promise.allSettled

When we’re working with multiple promises, especially when they are depends on each other, you'd always like to know the result of each promise. With Promise.allSettled, we can create a new promise that only returns when all of the promises passed to it are complete. This will give us access to an array with some data on each promise.

const p1 = new Promise((res, rej) => setTimeout(res, 1000));

const p2 = new Promise((res, rej) => setTimeout(rej, 1000));

Promise.allSettled([p1, p2]).then(data => console.log(data));

// [
//   Object { status: "fulfilled", value: undefined},
//   Object { status: "rejected", reason: undefined}
// ]

Nullish coalescing operator (??)

The nullish coalescing operator (??) is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand. If we have a object with some values, sometimes we want to allow for values that are technically falsy, like an empty string or the number 0. Setting default values quickly gets annoying since it’ll override what should be valid values.

let user = {
  profile: {
    name: "",
    age: 0
  }
};

console.log(user.profile.name || "userName"); // userName
console.log(user.profile.age || 22); // 22

Instead of using || operator we can use the double question marks operator to be a bit more type strict, which only allows the default when the value is null or undefined.

console.log(user.profile.name ?? "userName"); // ""
console.log(user.profile.age ?? 22); // 0

Optional Chaining Operator

Similarly to the nullish coalescing operator, the optional chaining operator also deals with null and undefined. We can return a value if what we want is undefined, but what if the path to it is undefined?

By adding a question mark before our dot notation we can make any part of a value’s path optional so we can still interact with it.

let user = {};

console.log(user.profile.name ?? "userName"); // user.profile is undefined
console.log(user?.profile?.name ?? "userName");
console.log(user?.profile?.age ?? 22);

GlobalThis

globalThis, providing a universal way to access the global this value. This means self for Web Workers, window for browsers, global for Node.js, and anything else for any runtime that correctly implements the ES2020 standard.

var getGlobal = function () { 
  if (typeof self !== 'undefined') { return self; } 
  if (typeof window !== 'undefined') { return window; } 
  if (typeof global !== 'undefined') { return global; } 
  throw new Error('unable to locate global object'); 
}; 

getGlobal() === globalThis; // true (for browser, Web Worker and Node.js)
globalThis === window; // true (if you're in browser)

String.matchAll()

Another new improvement-like method is String.matchAll(). Basically, if you've ever worked with RegExps before, String.matchAll() is a nice alternative to using RegExp.exec() in a while loop with the g flag enabled. That's all there's to it. It returns an iterator that contains all the match results - including capturing groups.

const regexp = /t(e)(st(\d?))/g;
const str = 'test1test2';

const array = [...str.matchAll(regexp)];

console.log(array[0]);
// expected output: Array ["test1", "e", "st1", "1"]

console.log(array[1]);
// expected output: Array ["test2", "e", "st2", "2"]

Also there is some more feature updates in ES2020. Anyway, if you enjoyed the content write me on Twitter. Read my Previous articles here.

Article on System Design Interview.

Thanks for reading and happy coding!