ESNext: JavaScript “Nullish Coalescing Operator”

UPDATE December 2019: This feature has now advanced to Stage-4 and will be part of the ES2020 Specification! 🎉

One of my favorite ECMAScript Proposals is the “Optional Chaining Operator”. Another proposal that forms great duo with it is the “Nullish Coalescing Operator” (sometimes also referred to as “Nullary Coalescing Operator”).

Both proposals still are Stage-1, but don’t let that stop us from taking a peek into it right now.

💁‍♂️ Stage-1?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-1 is the Proposal stage. It signals that the committee is showing interest in the proposal and that it is seeking further investigation on how to tackle it. At this stage the proposal is subject to heavy changes. It is only when a proposal reaches Stage 4 that it is ready to become part of the ECMAScript Specification.

~

The problem

As explained in the “Optional Chaining Operator” post we can get properties of an object in a fail safe way using Short-Circuit Logic or by using the proposed Optional Chaining operator (?.) in the nearby future:

// Today: Extract firstName using Short-Circuit Logic
const firstName = message.body && message.body.user && message.body.user.firstName;
// Near future: Extract firstName using the Optional Chaining Operator
const firstName = message.body?.user?.firstName;

A common technique used is to add a default fallback value using the logical OR operator (||):

const firstName = message.body?.user?.firstName || 'Stranger';

Whilst this works fine, there is one problem with falsy values: when the left hand side of the OR expression evaluates to falsy (e.g. null, undefined, false, 0, empty string, …), the right hand side of the expression will be used. For null and undefined that’s not a problem, but it is for false, 0, empty string, etc.:

const message = {
    settings: {
        animationDuration: 0,
        showSplashScreen: false
    },
};

const showSplashScreen = message.settings?.showSplashScreen || true;
// --> true 🚫

The result here is true (the fallback), even though message.settings.showSplashScreen was defined to be false.

~

The solution

The proposed Nullish Coalescing Operator ?? is intended to provide a solution to this problem. It serves as an equality check against nullary values (e.g.
null or undefined). Whenever the expression to the left of the ?? operator evaluates to either undefined or null, the value defined to the right will be returned.

Combined with the Optional Chaining Operator, our code snipped can be fixed like this:

const message = {
    settings: {
        animationDuration: 0,
        showSplashScreen: false
    },
};

const showSplashScreen = message.settings?.showSplashScreen ?? true;
// --> false 🎉

Small change, big impact 🙂

~

So, when can we us this?

You can use the Nullish Coalescing Operator today already thanks to Babel’s plugin-proposal-nullish-coalescing-operator plugin (for use with Babel 7).

Do note that the proposal still Stage-1 (soon Stage-2 by the looks of it) and might still change in the future.

~

In short

💻 The examples embedded in this post are part of a talk on ESNext named “What’s next
 for JavaScript?”, which I recently gave at a Fronteers België meetup and Frontend United 2018 (Utrecht). You can check the slides / a recording out here. I’m available for bringing this talk at your meetup/conference.

👋 This post also got published on Medium. If you like it, please give it some love a clap over there.

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)

ESNext: Dynamically import ES modules with “dynamic import()

UPDATE June 2019: This feature has now advanced to Stage-4 and will be part of the ES2020 Specification! 🎉

One of the recent ECMAScript proposals that landed in Chrome 63 is dynamic import():

Dynamic import() introduces a new function-like form of import, which allows one to import on demand. It returns a promise for the module namespace object of the requested module, which is created after fetching, instantiating, and evaluating all of the module’s dependencies, as well as the module itself.

Say you have a lightbox or dialogbox. You could offload its importing to the very moment it is needed:

button.addEventListener('click', async (event) => {
    try {
        const dialogBox = await import('./dialogBox.mjs');
        dialogBox.open(…);
    } catch (error) {
        // …
    }
});

Note that we’re using await here, as it’s better than the typical promise code which uses .then().

The proposal is currently Stage-3

💁‍♂️ Stage-3?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-3 is the Candidate Stage where the feature is considered complete and only critical changes will happen based on implementation experience. If all goes well the proposal will advance to Stage 4 without any changes, after which it will to become part of the ECMAScript Specification.

ESNext: JavaScript “Optional Chaining Operator”

UPDATE December 2019: This feature has now advanced to Stage-4 and will be part of the ES2020 Specification! 🎉

UPDATE: The proposed operator got renamed from “Null Propagation Operator” to “Optional Chaining Operator”. This post has been updated to include this change.

Earlier today I was delighted to see that the “Optional Chaining Operator” in JavaScript has entered stage-1. This little gem – which I know from Coffeescript – is a real timesaver, and is something I’ve been looking forward to.

💁‍♂️ Stage-1?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-1 is the Proposal stage. It signals that the committee is showing interest in the proposal and that it is seeking further investigation on how to tackle it. At this stage the proposal is subject to heavy changes. It is only when a proposal reaches Stage 4 that it is ready to become part of the ECMAScript Specification.

The problem

Let’s start at the beginning. Say we have this simple Object named message:

const message = {
  body: {
    user: {
      firstName: 'Bramus',
      lastName: 'Van Damme',
    },
  },
};

To access the firstName property of that object, we can use this snippet right here:

const firstName = message.body.user.firstName;

However, this isn’t really safe: if message.body.user were not to exist, we’d get a JavaScript error:

const thisWillFail = message.body.inexistent.firstName;
// --> "Cannot read property 'firstName' of undefined"

Uh oh!

The hacky workaround

To fix this we – at this moment – can reside to Short-Circuit Evaluation:

const firstName = message.body && message.body.user && message.body.user.firstName;

Shouldn’t that return true?

💁‍♂️ The reason that this works it because of JavaScript returning the last encountered value – and not a boolean – when using Short-Circuit Logic.

To include a default fallback value, we can add some more Short-Circuit Logic, using the || operator:

const firstName = (message.body && message.body.user && message.body.user.firstName) || 'Stranger';

If the expression to the left of the || operator were to evaluate to something falsy (e.g. null, undefined, false, 0, empty string, …), the value to the right will be used.

Alternatively one could also use something like this:

const firstName = (((message || {}).body || {}).user || {}).firstName || 'Stranger';

(… Yeah, I know!?)

The proper solution

Now enter the “Optional Chaining Operator” ?. which provides us with a very elegant syntax and fail-safe approach to the issue described above:

const firstName = message.body?.user?.firstName || 'Stranger';

Whenever the expression to the left of the ?. operator evaluates to either null or undefined the whole expression it belongs to will evaluate to undefined, thus falling back to the default defined using the ||:

const firstName = message.body?.inexistent?.firstName || 'Stranger';

In the example above message.body?.inexistent evaluates to undefined. Therefore the entire message.body?.inexistent?.firstName expression will be considered to be undefined.

As a result the interpreter will then evaluate const firstName = undefined || 'Stranger';, to finally return 'Stranger' as the value for firstName.

Here’s to hoping that this one reaches stage-4 any time soon. As far as I can tell this is not in Babel (yet) the Babel folks are working on it.

ECMAScript Proposal: Optional Chaining →

💻 The examples embedded in this post are part of a talk on ESNext named “What’s next
 for JavaScript?”, which I gave at a Fronteers België meetup and Frontend United 2018 (Utrecht). You can check the slides / a recording out here. I’m available for bringing this talk at your meetup/conference.

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)