JavaScript · Modern JavaScript (ES6+)

Optional Chaining & Nullish Coalescing in JavaScript — Safe Access Done Right

5 min read Updated 2026-06-18

Practice Optional Chaining & Nullish Coalescing interview questions

Tackling "cannot read property of undefined"

Few errors are as familiar as TypeError: Cannot read properties of undefined. It happens whenever you reach into a nested structure that isn't fully present. ES2020 introduced two operators that, together, make safe access and sensible defaults clean and concise: optional chaining (?.) and nullish coalescing (??). Used well, they replace verbose guard chains and subtle || bugs. Used carelessly, they can hide real problems. This guide covers both, how they combine, and when not to use them.

Optional chaining basics

The ?. operator accesses a property only if the value before it is not null or undefined. Otherwise the whole expression short-circuits to undefined instead of throwing.

const user = { profile: { name: 'Ada' } }
user.profile?.name       // 'Ada'
user.account?.balance    // undefined no error, even though account is missing
user.account.balance     // TypeError without ?.

Instead of user && user.account && user.account.balance, you write user?.account?.balance. The expression stops at the first nullish link and yields undefined.

Three forms of optional chaining

?. works for property access, dynamic (bracket) access, and method calls.

obj?.prop          // property access
obj?.[key]         // dynamic/computed access
obj?.method?.()    // method call — only calls if method exists
arr?.[0]           // array element

The method-call form is especially handy: obj.method?.() calls method only if it exists, avoiding "x is not a function" errors when an optional callback may be absent.

Short-circuiting

When ?. short-circuits, it abandons the entire rest of the chain — subsequent accesses and calls don't run at all.

const result = a?.b.c.d
// if `a` is null/undefined, b, c, AND d are all skipped -> result is undefined

This is important: you only need ?. at the link that might be nullish, not on every step, because short-circuiting protects the rest. That said, putting ?. at each genuinely-optional link documents your assumptions clearly.

Nullish coalescing basics

The ?? operator returns its right-hand side only when the left is null or undefined. It's the safe way to provide defaults.

const port = config.port ?? 8080      // use 8080 only if port is null/undefined
const name = user.name ?? 'Anonymous'

It pairs naturally with optional chaining to access-and-default in one expression:

const city = user?.address?.city ?? 'Unknown'   // safe access + fallback

The crucial ?? vs || distinction

This is the heart of why ?? exists. The old || operator returns the right side for any falsy value — including 0, '', false, and NaN — which causes bugs when those are valid values.

const count = data.count || 10    // if count is 0, you get 10!
const count2 = data.count ?? 10   // 0 is kept; only null/undefined -> 10

const label = input.text || 'N/A' // empty string becomes 'N/A'
const label2 = input.text ?? 'N/A' // '' is a valid value, kept

Rule of thumb: use ?? when 0, '', or false are legitimate values you want to keep, and || only when you genuinely want any falsy value to trigger the fallback.

Logical assignment operators

ES2021 added logical assignment operators that combine a logical operator with assignment: ??=, ||=, and &&=. They assign only when the condition holds.

config.timeout ??= 3000     // assign 3000 only if timeout is null/undefined
options.list ||= []         // assign [] only if list is falsy
user.active &&= validate()  // assign validate() only if active is truthy

??= is the safest for defaults — it sets a value only when the property is genuinely missing, preserving 0/''/false. These operators also short-circuit: the right side isn't evaluated when the assignment is skipped.

Combining ?. and ?? with precedence

?. and ?? work together, but there's a syntax rule: you cannot directly mix ?? with || or && without parentheses, because their precedence is intentionally ambiguous.

const x = a ?? b || c     // SyntaxError
const y = (a ?? b) || c   // explicit grouping required
const z = a ?? (b || c)   // also fine

This forced clarity prevents subtle bugs from mixed-operator expressions.

Don't over-use optional chaining

The biggest pitfall is reaching for ?. everywhere, which hides bugs. If a value should always exist, ?. silently turns a programming error into a quiet undefined that surfaces as a confusing failure later.

// if `user` should always exist, this masks the real bug
const name = user?.name

// let it throw loudly so you catch the actual problem
const name = user.name

Use ?. only where a value is legitimately optional (data that may or may not be present), not as a blanket shield over code you haven't reasoned about. Over-chaining makes failures harder to diagnose.

Optional chaining is for reading, not writing

You can't use ?. on the left side of an assignment — it's a read-only access operator.

obj?.prop = 5    // SyntaxError — invalid assignment target
if (obj) obj.prop = 5   // guard the write explicitly

For conditional writes, guard with a normal check or use ??=/||= on the property.

Key takeaways

  • ?. accesses a property/method only if the preceding value isn't null/undefined, short-circuiting to undefined instead of throwing.
  • It comes in property (?.prop), dynamic (?.[key]), and call (?.()) forms, and abandons the rest of the chain on a nullish link.
  • ?? returns the fallback only for null/undefined — unlike ||, it preserves 0, '', and false.
  • Logical assignment (??=, ||=, &&=) assigns conditionally and short-circuits; ??= is the safe default-setter.
  • You must parenthesize when mixing ?? with ||/&&.
  • Don't over-use ?. — it can mask real bugs; reserve it for genuinely optional values, and remember it can't be an assignment target.

Optional chaining and nullish coalescing make defensive code clean and intention-revealing — as long as you respect the falsy-vs-nullish distinction and don't paper over errors that should surface.

Practice tests are coming soon

Get notified when interactive mock interviews and quizzes launch.