DEV Community

Cover image for Optional Chaining in JavaScript: The Introduction
Natalie Smith 🏳️‍🌈
Natalie Smith 🏳️‍🌈

Posted on

Optional Chaining in JavaScript: The Introduction

What is Optional Chaining?

It's a new addition that has been added to ES2020 that allows us to check for object properties to make sure that they're not undefined or null.

What the problem is

Before, to check if an object's property was undefined, we could do something like this:

let nameLength = db.student.name.length 

Now, the problem is if db, student, or name is undefined it would throw a type error so let's try it another way.

let nameLength;
if(db && db.student && db.student.name) {
  nameLength = db.student.name.length
}

You could also use the ternary operator

const nameLength =
  (db
    ? (db.student
      ? (db.student.name
        ? db.student.name.length
        : undefined)
      : undefined)
    : undefined);

Okay, the last two examples are less error-prone but it doesn't exactly help readability so let's introduce optional chaining, shall we.

Introducing Optional Chaining

The problems have been presented so let's use the alternative to refactor the first example.

let nameLength = db?.student?.name?.length

It is characterized by the ?. operator and if db, student, or name is undefined then it won't throw an error, instead, nameLength will just be undefined.

Short-circuiting

First and foremost, what is short-circuiting?

Let's take a look at the || logical operator

In JavaScript, it will evaluate from left to right and if it finds a truthy value then it will "short-circuit" and not even look at the second operand.

true || false

Short-circuiting in optional chaining

Since it evaluates from left to right, if we look at the example below

let user = null;
let count = 0;

user?.increase(count++);

console.log(count);  // 0

The operator ?. will immediately "short-circuit" and not check the rest if the user doesn't exist.

Using square brackets [ ]

const optionName = 'optional setting';
const optionLength = db?.student?.preferences?.[optionName].length;

If the option name is undefined then opitionLength will just be undefined and if it is not undefined it will return the value

Function invocation

Similar to accessing the property with a square bracket, you can also invoke a function

const adminOption = db?.student?.validateSomeAwesomeFunction?.().option;

nullish coalescing ?? operator

Optional Chaining can be used with the nullish coalescing ?? operator when you need a default value.

const object = { id: 13, names: { first: 'Natalie', last: 'Smith' }};

const bio = object?.names?.bio ?? 'Tell us about yourself';

As you can see, since the property bio doesn't exist on the object, we just result back to the defaulted value.

Caveats

"A play on of Shakespeare To Be or Not To Be"

Don't overuse optional chaining as it only allows for us to check to see if a property value is undefined/null. If we did user?.favorites and the user is not defined then it will throw an error.

Equality Checks

Let's take a look at the following example

if(foo && bar && foo.opitionOne === bar.opitionTwo) {...}

and convert it to 

if(foo?.opitionOne === bar?.opitionTwo) {...}

In the first case without optional chaining, the condition will not be true unless both foo and bar are truthy. However, in the second case, if foo and bar are null, it will be truthy because foo and bar will return undefined, and thus, this can lead to an unexpected equality check and bugs.

Operator precedence

First and foremost, what is the operator precedence?

It determines the order in which operators(|| && ===) are evaluated much like CSS selectors(.class, #id, etc..) whichever one has higher precedence it will be evaluated first.

One thing to note is optional chaining has higher precedence than &&. So when going in to replace the && with optional chaining for an equality check and since && has lower precedence than ?. it might introduce an unexpected outcome especially since ?. will return undefined if it's not there.

Conclusion

Thank you for reading and if I missed something in this post please comment down below, I'm not an expert so feedback is always appreciated.

If you would like to buy me a coffee ☕️ that would be deeply appreciated as I am always tired 😴

Buy Me A Coffee

thank you

cover image from https://daqxzxzy8xq3u.cloudfront.net/wp-content/uploads/2019/10/21104843/javascript-optional-chaining.jpg

Top comments (2)

Collapse
 
gsiete profile image
Gabriel Poussif

I'd add in the Function invocation section a note on how this could throw an error if for some reason we could expect the value to be false. Specially if one comes from using something like student.validateSomeAwesomeFunction && student.validateSomeAwesomeFunction();
(I think it can be more common in passed props on React, as it happened to me)

Collapse
 
kdfemi profile image
MiniSoda

Nice one, i have been waiting for this since, this is available in Angular Html template and i love it