DEV Community

Cover image for Improvements to JavaScript in the new ES2020 standard 🎁
Vic Shóstak
Vic Shóstak

Posted on • Updated on

Improvements to JavaScript in the new ES2020 standard 🎁


Hi, DEV community 👋 How're you today?

Let's talk about the modern JavaScript standard → ES2020. Personally, all these new features make me hope that JS will become even more convenient and understandable language, than it is now.

Here we go! 👇

📝 Table of contents

⚡ Breaking news

12 Jun 2020, The ECMA International General Assembly approved specifications, that will be discussed in this article!

  • ECMA262 (ECMAScript® 2020 Language Specification)
  • ECMA402 (ECMAScript® 2020 Internationalization API Specification)

Congratulations on our new JavaScript! 😄

Nullish coalescing


In JavaScript there are "false" and "true" values. Now we can say that "zero" values have been added to them as well. Such values include null and undefined values.

In JavaScript world, "false" values are:

  1. empty lines
  2. number 0
  3. undefined values
  4. null
  5. false
  6. NaN

But an expression to check the value to see if it's "zero", will return true only for null and undefined. For example:

const value1 = true;
const value2 = false;
const value3 = undefined;
const value4 = null;

// Function to check values
const getValue = (value) => {
    if (value || value === false) return value;
    return true;

getValue(value1); // => true
getValue(value2); // => false
getValue(value3); // => true
getValue(value4); // => true
Enter fullscreen mode Exit fullscreen mode

But ES2020 standard has enough operator ?? to test for null and undefined. You can do it, even without the conditional if operator!

Just rewrite getValue function to:

const getValue = (value) => value ?? true;
Enter fullscreen mode Exit fullscreen mode

That's all it takes. Elegant, understandable and professional! 👍

↑ Table of contents

Optional chaining


Optional chains allow to organize safe access to deeply nested properties of objects without the need to verify the existence of each of them. Let's take a look at exactly how this feature works.

For example, we have this object:

const user = {
    firstName: "John",
    lastName: "Doe",
    address: {
        zip: 100001,
        city: "New York",
        street: "Long str.",
        apartments: 13,
        prop1: {
            prop2: {
                prop3: {
                    prop4: {
                        value: 42
Enter fullscreen mode Exit fullscreen mode

And we have the task of getting values from address.street and ...prop4.value. Today, we're dealing with it somehow:

if (user && user.address) {
    console.log(user.address.street); // => Long str.

if (user && user.address && user.address.prop1 && user.address.prop1.prop2 && 
    user.address.prop1.prop2.prop3 && user.address.prop1.prop2.prop3.prop4) {
    console.log(user.address.prop1.prop2.prop3.prop4.value); // => 42
Enter fullscreen mode Exit fullscreen mode

Huge, ugly and not understandable, right? Okay. Look at the magic, that a new ES2020 standard allows you to do:

console.log(user?.address?.street); // => Long str.
console.log(user?.address?.prop1?.prop2?.prop3?.prop4?.value); // => 42
Enter fullscreen mode Exit fullscreen mode

Is this cool! 🔥 We no longer need massive if...else conditions. Less code, less bugs and bundle size. But, it's not all! What, if we're make mistake and call unknown_var?

// Current JS standard:
console.log(user.address.prop1.unknown_var); // => error? undefined? ...?

// ES2020:
console.log(user?.address?.prop1?.unknown_var); // => undefined
Enter fullscreen mode Exit fullscreen mode

Yep, we get a single value of a non-existent variable like undefined. Always.

↑ Table of contents

Dynamic imports


This technology allows you to import JavaScript files dynamically, as modules, without any additional tools. In this case, if a module is not needed, it is not imported.

Yes, this can be made easier by taking advantage of lazy module loading, for example, by using a code-splitting technology available in Webpack (and not so)... but using it means wasting some system resources. 🤷

Code example for current JS standard:

import { share } from "./share.js"; // => always load module

const shareButton = document.querySelector(".button__share");

shareButton.addEventListener("click", share); // => do something, if clicking
Enter fullscreen mode Exit fullscreen mode

But in ES2020, we've a standard way to dynamically load modules:

const shareButton = document.querySelector(".button__share");

shareButton.addEventListener("click", () => {
    import("./share.js")                   // => load module, only if needed
      .then((module) => module.share())    // => do something, if clicking
      .catch((error) => console.log(err)); // => handle error
Enter fullscreen mode Exit fullscreen mode

↑ Table of contents

js es2020

Global property globalThis


On the web, global property accessible as window or self or this. On Node.js as global or this. And it's not a full list!

The global property globalThis solve this trouble. It stores a reference to a global object corresponding to the environment where your code is executed.

No more guessing, what to call in code!

↑ Table of contents

Arbitrary precision integers (BigInt)


A new BigInt data type allows you to work with numbers that are longer, than the length of numbers that you could work with in JavaScript before (253).

// Current JS standard:
let n = Number.MAX_SAFE_INTEGER; // => 9007199254740991, this is 1 less than 2^53

const a = n + 1; // => 9007199254740992, ok, checks out
const b = n + 2; // => 9007199254740992, wait, that’s the same as above!

// ES2020:
let n = BigInt(Number.MAX_SAFE_INTEGER); // => 9007199254740991

const c = n + 1n; // => 9007199254740992n
const d = n + 2n; // => 9007199254740993n, this works now!
Enter fullscreen mode Exit fullscreen mode

A BigInt is created by appending n to the end of the integer or by calling the constructor.

↑ Table of contents

Promise.allSettled method


The Promise.allSettled method will be useful, if you need your code to be executed after you have finished all promises.

Of course, you can use the Promise.all() method... but it will generate an error, if at least one promise passed to it is rejected. For example:

const array = [
    Promise.resolve("Data release"),
    Promise.reject(new Error("Something went wrong")),

  .then((data) => console.log("all resolved! values:", data))
  .catch((err) => console.log("got rejected! reason:", err)); 

// got rejected! reason: null
Enter fullscreen mode Exit fullscreen mode

But with Promise.allSettled method, promise is successfully resolved only after the work of other promises has been completed. And it doesn't matter, if they have been successfully or unsuccessfully executed.

  .then((res) => console.log(res))
  .catch((err) => console.log(err));

// [
//     { status: "fulfilled", value: 100 },
//     { status: "rejected", reason: null },
//     { status: "fulfilled", value: "Data release" },
//     { status: "rejected", reason: Error: Something went wrong }
// ]
Enter fullscreen mode Exit fullscreen mode

↑ Table of contents

Photo by

[Title] Oskar Yildiz
[1] Caspar Camille Rubin


If you want more articles like this on this blog, then post a comment below and subscribe to me. Thanks! 😘

And, of course, you can support me by donating at LiberaPay. Each donation will be used to write new articles and develop non-profit open-source projects for the community.

Support author at LiberaPay

Top comments (2)

bernardbaker profile image
Bernard Baker

Dynamic imports are great.. and optional chaining rocks.

koddr profile image
Vic Shóstak

Yep! It's very helpful to reduce size of bundle... and looks great 😉