Optional Chaining in JavaScript (feat. Nullish Coalescing)

Faisal Rahman
4 min readOct 23, 2020
Image source: Pexels

ES2020 introduced a new feature for JavaScript: optional chaining. Optional chaining is achieved with using a new operator comprised of a question mark followed by a dot (?.). People familiar with Ruby may find it similar to Ruby’s safe navigation operator (&.), both in semantics and in functionalities. Optional chaining operator helps us access deeply nested object properties safely and concisely, and much more.

Life Before Optional Chaining

Unlike other primitive types that will automatically be boxed into objects during evaluation, JavaScript will throw a TypeError whenever we try to access a property of ‘nullish’ values, which are undefined and null. This is due to undefined and null being the sole member of their respective types, both types don’t have type objects. This mechanism becomes important when we work with object properties, since accessing a nonexistent property of an object will yield undefined, which in turn will lead to TypeError should we try to access further properties.

const obj = {};obj.foo; // undefined
obj.foo.bar; // TypeError: cannot read property 'bar' of undefined

Often, we need to access properties we’re not sure whether it exists. We often end up relying on logical operators (&& and ||) to navigate through the uncertainty by truthiness checking and fallback value setting.

const obj = {};obj.foo && obj.foo.bar || "There's no foo nor bar!";

The common mistake with that method is that we equate truthiness with existence, which can easily produce false negatives when it encounters falsy values.

const obj = { foo: { bar: 0 } };obj.foo && obj.foo.bar || "There's no... hang on a minute";

Ultimately we end up strictly checking against undefined and null, which will lead us to writing this dreaded train of property access.

const obj = {};(typeof obj.foo !== 'undefined' && obj.foo !== null) && (typeof obj.foo.bar !== 'undefined' && obj.foo.bar !== null) ? obj.foo.bar : "Now this is more like it!";

There must be a better way to do that, right?

Enter Optional Chaining

The entire train of property access from the example above can be written more concisely with the help of optional chaining operator (?.) as such:

const obj = {};obj.foo?.bar; // undefined. No TypeError, wayyyy shorter, yay!

Now, what does that operator do? It checks the expression on the left hand side (LHS) of it, whether it evaluates to a nullish value. If it does, the whole expression (‘train’, if I may) will evaluate to undefined. What about the right hand side (RHS) expression? It will not be evaluated at all, which is why optional chaining operator can be called short-circuiting.

However, be aware that each operator evaluates separately. That is, after it passes on the first encounter, it will evaluate the right hand side expression as usual, no longer evaluating to undefined should there be any attempt to access a non-existent property along the line. This is intentional design so that programmers could indicate branching more precisely, allowing them to debug their code more easily if a bug happens later.

const obj = { foo: {} };obj.foo?.bar.baz; // TypeError since foo exists but bar evaluates to undefined
obj.foo?.bar?.baz; // undefined, this is fine

Pretty cool, right? Don’t go anywhere just yet, because it’s still got some tricks up its sleeve! Optional chaining operator can also be used to optionally access object properties dynamically, or optionally call a method.

obj.foo?.[Math.floor(Math.random() * 10)];obj.foo?.reduce?.(reduceFn);

One thing about that optional method call, though. You may think it will not try to call the method if it’s not a function, but that’s not the case. It will still evaluate the same, that is it will not evaluate the right hand side expression if and only if the left hand side expression evaluates to either undefined or null. Be careful!

Set a Fallback with Nullish Coalescing Operator

We have seen how optional chaining operator supplants && (which should not be used in the first place) in safely accessing object properties. What can we use to replace ||, to set a fallback value? Let me introduce you to nullish coalescing operator (??), another new feature introduced in ES2020.

Nullish coalescing operator returns the right hand side expression if the left hand side expression evaluates to undefined or null. Otherwise, it will return the left hand side operand. It is designed to complement optional chaining operator as a way for programmers to set fallback values. We can write object property accesses even more concise with both operators.

const obj = {};obj.foo?.bar ?? "No bar for you";

Similar with optional chaining operator, this operator short-circuits, so the right hand side expression will not be evaluated if the left hand side is neither undefined nor null.

let message = "just a message";
const obj = { message: "cool" };
obj.message ?? (message = "obj doesn't have a message");console.log(message); // "just a message"

What Optional Chaining Doesn’t Do

In its development, the TC39 team considered some more expressions, but they ultimately decided not to support them due to various reasons, mostly lack of real world use cases. or the expression was deemed to be too confusing. Here are some unsupported expressions mentioned in the proposal:

  • Object construction: new a?.()
  • Template literals: a?.`string`
  • Constructors or template literals in/after an optional chain: new a?.b(), a?.b`string`
  • Optional assignment: a?.b = c
  • Super: super?.(), super?.foo

References

--

--

Faisal Rahman

Engineering for Education. In love-hate relationship with JavaScript.