DEV Community

Zaid Rehman
Zaid Rehman

Posted on

1

Stage 4: Optional chaining

Motivation
When looking for a property value that's deep in a tree-like structure, one often has to check whether intermediate nodes exist or not like below

const street = user.address && user.address.street;
Enter fullscreen mode Exit fullscreen mode

Also, many API return either an object or null/undefined, and one may want to extract a property from the result only when it is not null

const fooInput = myForm.querySelector('input[name=foo]')
const fooValue = fooInput ? fooInput.value : undefined
Enter fullscreen mode Exit fullscreen mode

The Optional Chaining Operator allows a developer to handle many of those cases without repeating themselves and/or assigning intermediate results in temporary variables:

var street = user.address?.street
var fooValue = myForm.querySelector('input[name=foo]')?.value
Enter fullscreen mode Exit fullscreen mode

The call variant of Optional Chaining is useful for dealing with interfaces that have optional methods

iterator.return?.() // manually close an iterator
Enter fullscreen mode Exit fullscreen mode

or with methods not universally implemented

if (myForm.checkValidity?.() === false) { // skip the test in older web browsers
    // form validation fails
    return;
}
Enter fullscreen mode Exit fullscreen mode

Syntax
The Optional Chaining operator is spelled ?.. It may appear in three positions:

obj?.prop       // optional static property access
obj?.[expr]     // optional dynamic property access
func?.(...args) // optional function or method call
Enter fullscreen mode Exit fullscreen mode

Semantics
If the operand at the left-hand side of the ?. operator evaluates to undefined or null, the expression evaluates to undefined. Otherwise the targeted property access, method or function call is triggered normally.

a?.b                          // undefined if `a` is null/undefined, `a.b` otherwise.
a == null ? undefined : a.b

a?.[x]                        // undefined if `a` is null/undefined, `a[x]` otherwise.
a == null ? undefined : a[x]

a?.b()                        // undefined if `a` is null/undefined
a == null ? undefined : a.b() // throws a TypeError if `a.b` is not a function
                              // otherwise, evaluates to `a.b()`

a?.()                        // undefined if `a` is null/undefined
a == null ? undefined : a()  // throws a TypeError if `a` is neither null/undefined, nor a function
                             // invokes the function `a` otherwise
Enter fullscreen mode Exit fullscreen mode

Short-circuiting

a?.[++x]         // `x` is incremented if and only if `a` is not null/undefined
a == null ? undefined : a[++x]
Enter fullscreen mode Exit fullscreen mode

Stacking

a?.b[3].c?.(x).d
a == null ? undefined : a.b[3].c == null ? undefined : a.b[3].c(x).d
// (as always, except that `a` and `a.b[3].c` are evaluated only once)
Enter fullscreen mode Exit fullscreen mode

Optional deletion

delete a?.b
a == null ? true : delete a.b
Enter fullscreen mode Exit fullscreen mode

AWS Q Developer image

Your AI Code Assistant

Generate and update README files, create data-flow diagrams, and keep your project fully documented. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Instrument, monitor, fix: a hands-on debugging session

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️