DEV Community

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

Posted on • Edited on

Improvements to JavaScript in the new ES2020 standard 🎁

Introduction

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

Proposal: https://github.com/tc39/proposal-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

Proposal: https://github.com/tc39/proposal-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

Proposal: https://github.com/tc39/proposal-dynamic-import

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

Proposal: https://github.com/tc39/proposal-global

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)

Proposal: https://github.com/tc39/proposal-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

Proposal: https://github.com/tc39/proposal-promise-allSettled

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(100),
    Promise.reject(null),
    Promise.resolve("Data release"),
    Promise.reject(new Error("Something went wrong")),
];

Promise.all(array)
  .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.

Promise.allSettled(array)
  .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 https://unsplash.com/photos/cOkpTiJMGzA
[1] Caspar Camille Rubin https://unsplash.com/photos/0qvBNep1Y04

P.S.

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

❗️ You can support me on Boosty, both on a permanent and on a one-time basis. All proceeds from this way will go to support my OSS projects and will energize me to create new products and articles for the community.

support me on Boosty

And of course, you can help me make developers' lives even better! Just connect to one of my projects as a contributor. It's easy!

My main projects that need your help (and stars) 👇

  • 🔥 gowebly: A next-generation CLI tool that makes it easy to create amazing web applications with Go on the backend, using htmx, hyperscript or Alpine.js and the most popular CSS frameworks on the frontend.
  • create-go-app: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.

Other my small projects: yatr, gosl, json2csv, csv2api.

Top comments (2)

Collapse
 
bernardbaker profile image
Bernard Baker

Dynamic imports are great.. and optional chaining rocks.

Collapse
 
koddr profile image
Vic Shóstak

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