JavaScript ES2024 ·
✓ verified by execution on 2026-08-15
When working with nested data, you often need to access a property deep inside an object. But if any part of that path is missing, your code will crash with the dreaded Cannot read properties of undefined error.
The optional chaining operator (?.) prevents this by stopping the access if it encounters null or undefined.
Safe Property Access
If you try to read a property from null, JavaScript throws an error. With ?., it simply returns undefined.
javascript
const user = null;console.log(user?.name);
Output
undefined
Your output
This is especially powerful when navigating nested objects. You don’t need to write long if statements to check if user exists and if user.profile exists before reading age.
javascript · visualize
const user = { details: { name: 'Alice' } };console.log(user.profile?.age);
As you step through the code above, notice how execution stops right at the ?. when user.profile evaluates to undefined.
Optional chaining short-circuits the evaluation and returns undefined immediately.
Arrays and Functions
You can also use the optional chaining operator with bracket notation to safely access array elements. The ?. comes right before the bracket.
It even works with function calls. You can use optional chaining when attempting to call a method which may not exist. If the method is absent, it safely returns undefined instead of throwing an error.
javascript
const user = { sayHi() { console.log('Hi'); } };user.sayHi?.();user.sayBye?.();
Output
Hi
Your output
The Nullish Coalescing Operator (??)
When optional chaining returns undefined, you often want to provide a fallback value. The nullish coalescing operator (??) returns its right-hand side operand when its left-hand side operand is null or undefined.
javascript
const score = null;console.log(score ?? 10);
Output
10
Your output
This pairs perfectly with optional chaining:
javascript
const data = null;console.log(data?.items ?? 'No items');
Output
No items
Your output
Common Misconceptions: || vs ??
You might be used to using the logical OR operator (||) to provide default values. But there is a critical difference: || falls back if the value is any falsy value, like 0 or an empty string "".
Nullish coalescing (??) only falls back for null or undefined.
Predict the outputjavascript
Read the code. What exactly will it print? Commit to an answer before you look.
In the example above, 0 is a valid number of retries. The ?? operator respects the 0, while the || operator treats it as falsy and overwrites it with 3.
Check yourself
What does the optional chaining operator (?.) return if the property doesn't exist?
Reveal answer
It returns undefined — Optional chaining short-circuits and returns undefined. It never returns null, even if the object itself was null.
Is the nullish coalescing operator (??) exactly the same as logical OR (||)?
Reveal answer
No, || falls back on any falsy value, while ?? only falls back on null or undefined — Logical OR (||) treats 0 and an empty string as falsy, triggering the fallback. Nullish coalescing (??) correctly treats 0 and empty strings as valid values, only falling back for null or undefined.
Do you need to use ?. on every single property in a long chain just to be safe?
Reveal answer
No, you only need ?. at the exact point where a value might be null or undefined — You only need ?. at the point where a value might be nullish. If it short-circuits, the rest of the chain will not execute, so subsequent dots do not need it unless they independently might be nullish.
Can you use optional chaining to assign a value, like user?.name = "Alice"?
Reveal answer
No, it causes a SyntaxError — Optional chaining is strictly for reading values or calling functions. It causes a SyntaxError if used on the left side of an assignment.
Challenges
Challenge 1 +10 XP
Write a function `getCity(user)` that safely returns the user's `address.city` using optional chaining, or `"Unknown"` using nullish coalescing if any part of the address is missing.
javascript
Test 1 (input: "{\"address\": {\"city\": \"Tokyo\"}}") — expects "Tokyo"
Test 2 (input: "null") — expects "Unknown"
Need a hint? (−25% XP)
Chain `user?.address?.city` and use `??` for the fallback.
Show solution (0 XP)
import fs from 'node:fs';const user = JSON.parse(fs.readFileSync(0, 'utf-8'));function getCity(user) { return user?.address?.city ?? "Unknown";}console.log(getCity(user));
🐞 Bug Hunt+15 XP
This configuration loader uses `||` to provide a default volume. But when a user tries to mute the sound by passing `0`, the game blares at full volume `100`! Fix the bug.
This code runs. It just does the wrong thing. Read it, find the defect,
fix it — the tests below decide when you are right.
javascript
Test 1 (input: "{\"volume\": 50}") — expects "50"
Test 2 (input: "{\"volume\": 0}") — expects "0"
Test 3 (input: "{}") — expects "100"
Need a hint? (−25% XP)
The `||` operator treats `0` as falsy. What operator only falls back for `null` or `undefined`?