September 23, 2023

Thoughts on New ES2020 Optional Chaining in Javascript

One of the best features introduced in Javascript’s newest ES2020 version is the Optional Chaining Operator. If you have a little bit of Javascript coding experience under your belt, just know that optional chaining is here to save us from one of the most annoying Javascript coding mistakes we make. And if you don’t have much Javascript coding experience, be happy you wouldn’t have to know how desirable denting a hole through your laptop sometimes seemed before optional chaining.

Javascript without optional chaining

Say you are trying to read the checked value from a radio input and do something with it.

let checkedInput = document.querySelector('input[type="radio"]:checked')
if (checkedInput.value == "1") {
    //Do something if checked value is 1
}
else {
    //Do something else
}

This code will work as you expect as long as at least one radio button is checked by the time this code starts running. But if it is not, then you get an error because checkedInput is undefined and you can’t read the value of an undefined object. Before-ES2020 method of solving this problem involves first checking whether a radio button is actually checked, and if checked, then reading the value.

if (checkedInput && checkedInput.value == "1") {
    //Do something if checked value is 1
}

At first glance, it may not seem like much hassle. But when you keep coming across instances like this while coding, some resulting in even longer lines of code more times than you’d like to admit, being annoyed becomes an inevitable ending.

Optional chaining to the rescue

With optional chaining, the solution is only an addition of an extra question mark.


if (checkedInput?.value == "1") {
    //Do something if checked value is 1
}

?. is called the optional chaining operator. With the addition of the optional training operator, instead of throwing an error, checkedInput.value returns undefined if checkedInput is null or undefined. If checkedInput is not null or undefined, it behaves normally.

Accessing Deeply Nested Object Properties with Optional Chaining

Say you have a nested object more than one level deep. When you want to access a property in the third level, the old way was to verify every level above the third level is not null or undefined and then access the property in the third level. Optional chaining eliminates the need to do that.

let person = {
    name: "Sam",
    pet: {
        dog: {
            name: "Rover",
            age: 8
        }
    }
}
let cat = person.pet.cat.name //Throws an error;
//The old way of doing this
let cat = person.pet && person.pet.cat && person.pet.cat.name 
//New way of doing this with  optional chaining, returns undefined
let cat = person.pet?.cat?.name 

Accessing array items with optional chaining

You can use optional chaining to access array items without first verifying whether the array exists.

let arrayItem = arr?.[4] //Returns undefined if 'arr' is null/undefined, 'arr[4]' otherwise

Optional chaining with functional calls

There are two ways to use optional chaining when it comes to function calls.

The first is to call a function on an object and not throw an error if the object is null or undefined.

data?.doSomething() //Undefined if 'data' is null/undefined, otherwise calls 'doSomething' on 'data'

The second way is to call a function that may not exist without throwing an error. This is especially useful when dealing with an API that may have removed the older methods while updating legacy code or when some features are unavailable in user devices.

data.doSomething?.() //Undefined if 'doSomething' does not exist, otherwise calls 'doSomething' on 'data'

In both cases, instead of throwing an error, undefined is returned because of the use of optional chaining.

Short circuiting

Another interesting use of optional chaining is its ability to evaluate an expression on the RHS depending on whether the expression on the LHS is null or undefined. This concept is called short-circuiting

let a = null
let x = 5
//Increment 'x' by one if 'a' is not null/undefined; 
a?.[++x] //x = 5, 'x' does not change because 'a' is null
a = 7 
a?.[++x] //x = 6, 'x' changes because 'a' is not null or undefined

Optional chain stacking

Optional chaining gives you the freedom to stack more than one optional chaining operator in one expression. That is, within the same expression, one optional chain can be followed by many others.

person.pet?.dog?.getBreed?.().name

Optional Chaining with Nullish Coalescing Operator

To get the maximum benefit of the new optional chaining operator, you have to combine it with the nullish coalescing operator (??).

Now, if you don’t know what a nullish coalescing operator is, don’t be afraid of the name, it’s a simple operator that is used to assign a default value to a variable if the expression on the left side of the operator turns out to be null or undefined.

let age = person.age ?? "Age not given" //'Age not given' if 'person.age' is null/undefined, 'person.age' otherwise

When used with optional chaining, nullish coalescing operator can be used to assign a default value in case some property or function on the left side expression is not available.

let catName = person.pet?.cat?.name ?? "No cat name given" //'No cat name given' if left expression is null/undefined

What is not Allowed with Optional Chaining?

You can’t use optional chaining on the left-hand side of an assignment.

person.pet?.cat?.name = "Henley" //Assignement not allowed

You can’t use optional chaining to check for an optional constructor like this.

let dog = new Dog?.()

Conclusion:

ES2020’s optional chaining is one of the major changes introduced to Javascript in the new release. In my opinion, it is also here to save Javascript programmers from the frustration of getting annoying little errors every time you forget to verify the existence of an object property or a function. Since this feature is still a new release, you have to be careful with using it on older browser versions. Google Chrome v80 and Firefox v74 are among the few browsers that currently support the implementation. It may take a while to come on board in all the browsers and platforms, but once it does, optional chaining will become something you cannot live without.