cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Nullish coalescing & optional chaining

Handle missing values with ?? and ?. instead of long checks, while preserving useful values like 0, false, and the empty string.

By the end, you can
  • 01
    Choose the right backupUse ?? when only null and undefined should fall back, and know when || is still right.
  • 02
    Read safely through missing dataUse ?. on properties, brackets, and calls without hiding real TypeErrors.
  • 03
    Fill or update values in placeUse ??=, ||=, and &&= with a clear mental model of what each one tests.

Missing, not merely empty

The previous Logical operators lesson showed why count || 10 is dangerous when count can be 0. JavaScript now has a sharper tool for that exact problem: nullish coalescing, written ??.

Nullish means exactly null or undefined. It does not mean every falsy value. A muted volume of 0, an answered checkbox of false, and an intentionally blank string can all be real data.

The one-line definition

Use ?? when only null and undefined should fall back, and use ?. when a property or call is genuinely optional and should become undefined instead of throwing.

Real-life analogy?? is a backup plan

Imagine arranging a trip. If the first plan is completely missing, you use the backup. But if the plan says “walk zero blocks” or “do not send a reminder,” that is still a plan. ?? is that careful backup rule.

In real life: No plan at all
In JavaScript: null or undefined: use the backup
In real life: A plan that costs ₹0
In JavaScript: 0: keep it
In real life: A quiet no
In JavaScript: false: keep it
In real life: A blank label chosen on purpose
In JavaScript: "": keep it

Where the analogy stops: A human might ask follow-up questions about whether a blank plan is useful. JavaScript follows the exact rule: only null and undefined trigger ??.

Optional chaining, written ?., solves a related problem. It lets you read through data that may be incomplete without writing the same long guard again and again.

The ?? backup operator

INTERACTIVE

left ?? right asks one narrow question: “is left null or undefined?” If yes, it returns right. Otherwise it returns left unchanged.

const displayName = user.name ?? "Anonymous";
const volume = savedVolume ?? 50;
const city = userCity ?? "Unknown";

This is not type conversion. JavaScript is not turning 0 into true or false before deciding. It is checking for the two missing-value markers from the Booleans, null & undefined lesson.

Compare ?? with ||
Fallback comparisonPop out in the code editor (opens in a new tab)JavaScript
const value = 0;console.log(value || "default");console.log(value ?? "default");
Real resultDifferent
value
0
value || "default"
default
value ?? "default"
0
Try it yourself
Pick the value used on line 1

The two operators differ here. || replaces any falsy value; ?? replaces only null or undefined.

The code is fixed except for line 1. Results are computed by the component, not guessed.
Real differences between || and ??
ValueWith ||With ??Lesson
0"default"0Yes — 0 is falsy but not nullish.
"""default"""Yes — an empty string can be a deliberate value.
false"default"falseYes — false is a real boolean answer.
NaN"default"NaNYes — NaN is falsy, but it is not null or undefined.
null"default""default"No — both fall back.
undefined"default""default"No — both fall back.

So || is not wrong. It is just a different question: “is the left side falsy?” Use it when blanks, zero, false, and NaN should all be rejected. Use ?? when those values might be meaningful.

Optional chaining on properties, brackets, and calls

STEP THROUGH

In the Logical operators lesson you saw guard chains like user && user.address && user.address.city. Optional chaining is the direct version: user?.address?.city.

Real-life analogy?. checks that the door exists

Walking down a hallway, you check that the next door exists before trying to open it. If there is no door, you stop instead of crashing into a wall. That is ?.: stop at missing links and produce undefined.

In real life: A hallway has no next door
In JavaScript: The value before ?. is null or undefined
In real life: Stop calmly
In JavaScript: The chain returns undefined
In real life: The door exists
In JavaScript: JavaScript opens it and continues the read
In real life: A sign says door, but it is not a real door
In JavaScript: A property exists but is not a function: ?.() can still throw

Where the analogy stops: The analogy explains missing links. It does not mean optional chaining validates every value or fixes wrong data shapes.

Optional chaining has three common forms: property reads, obj?.name; bracket reads, arr?.[0] or obj?.[key]; and optional calls, fn?.() or obj.method?.().

Step through optional chaining
Step 0 of 9Ready
Your turn: follow the blue line

Switch the starting user, then step through real optional chaining results. Predict whether each read returns a value, undefined, or a caught TypeError.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
let checks = 0;function mark(label) {  checks += 1;  return label;}function riskyCity() {  try {    return user.address.city;  } catch (error) {    return error.name;  }}const safeCity = user?.address?.[mark("city")];const firstTag = user?.tags?.[0];const greeting = user?.greet?.();const noFunction = undefined;const optionalCall = noFunction?.();const notCallable = (() => {  try {    return ({ run: 7 }).run?.();  } catch (error) {    return error.name;  }})();const missingUser = null;const skipped = missingUser?.[mark("skipped")];console.log(riskyCity(), safeCity, firstTag, greeting, optionalCall, notCallable, checks, skipped);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Switch the user on line 1

Changing the user starts the replay again. Watch whether mark("city") runs.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

Notice the precise limit: ?. checks only the value immediately before it. It short-circuits when that value is null or undefined. If the property exists but is the wrong kind of value, normal JavaScript rules still apply.

??=, ||=, and &&=

STEP THROUGH

Logical assignment operators update a variable or property only when the matching logical operator says to. They are shortcuts, but they are also readable when the intent is simple.

  • x ??= y: fill this box only if it is empty, meaning nullish.
  • x ||= y: replace it if it is falsy.
  • x &&= y: update it only if something truthy is already there.
Fill, replace, or update in place
Step 0 of 7Ready
Your turn: follow the blue line

Step through logical assignment. Watch how ??= keeps 0, ||= replaces an empty string, and &&= updates only an existing truthy value.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
const user = { nickname: "  Ada  " };settings.volume ??= 50;settings.theme ||= "light";settings.retries &&= settings.retries + 1;user.nickname &&= user.nickname.trim();console.log(settings.volume, settings.theme, settings.retries, user.nickname);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Choose the starting object on line 1

Try “Volume is 0” to prove ??= keeps 0 while ||= still replaces an empty string.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

The most important beginner mistake is using ||= for settings where 0 is meaningful. A muted volume should stay muted.

Rules and syntax traps

SYNTAX

JavaScript intentionally rejects a few expressions that look tempting. The first rule: do not mix ?? with && or || unless you add parentheses.

SyntaxError: missing parenthesesPop out in the code editor (opens in a new tab)JavaScript
const a = null;
const b = "backup";
const c = "last";
console.log(a || b ?? c);
Valid: grouping is explicitPop out in the code editor (opens in a new tab)JavaScript
const a = null;
const b = "backup";
const c = "last";
console.log((a || b) ?? c);

The second rule: optional chaining cannot be the target of assignment. This is invalid because JavaScript cannot store a property on “maybe nothing.”

SyntaxError: optional chain on the leftPop out in the code editor (opens in a new tab)JavaScript
const obj = { a: 1 };
obj?.a = 2;
Let required values fail loudly

Do not sprinkle ?. everywhere just to avoid errors. If a value must exist, an early TypeError may be the clearest signal that your data or program state is wrong.

Where you’ll use this

You will see these operators around profiles, configuration, optional callbacks, and data from outside your program. Objects and arrays get their own full lessons in Stage 3, so read the examples as simple containers: { name: "Ada" } has named properties, and ["admin"] has items by index.

A practical profile formatterPop out in the code editor (opens in a new tab)JavaScript
const user = { name: "Asha", address: { city: "Pune" }, nickname: "" };
const displayName = user.nickname ?? user.name ?? "Guest";
const city = user.address?.city ?? "Unknown";
const firstRole = user.roles?.[0] ?? "reader";
console.log(displayName, city, firstRole);

Line 2 keeps an empty nickname because ?? treats it as present. If your product says blank nicknames should fall back, that specific line should use || instead. Operator choice follows the product rule.

?? or ||?
  • A saved volume can be 0, meaning muted.
  • A product price can legitimately be 0 for a free item.
  • A username must not be empty, so "" should use Guest.
  • A menu label should fall back when it is "".
  • A saved checkbox can be false, meaning the person opted out.
  • A search box should show All items when the query is blank.
Try it yourself
0 of 6 correct

Sort each scenario by whether falsy values should be preserved or rejected.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Common misconceptions

  • “Nullish means falsy.” No: nullish means only null or undefined.
  • “?? is a better ||.” It is different, not universally better.
  • “?. makes a whole expression safe.” It protects only the link where you put it.
  • “method?.() checks whether it is a function.” It skips missing methods, but non-functions still throw.
  • “Logical assignment is just shorter.” It also communicates the exact condition for assigning.
  • “Use ?. everywhere.” Required data should fail loudly so bugs are visible.
Similar-looking tools, different questions
ToolQuestion it asksGood forCareful
??Is the value null or undefined?Preserving 0, false, and blank stringsNot a blank-string validator
||Is the value falsy?Rejecting any blank, zero, false, or NaN valueCan overwrite real choices
?.Is this link nullish?Reading optional nested dataCan hide bugs if the data is required
??=Is this place nullish?Filling missing settingsKeeps 0 by design
||=Is this place falsy?Replacing empty UI labelsOverwrites 0 and false
&&=Is this place truthy?Updating existing strings or flagsSkips empty strings and 0

Practice exercises

5 EXERCISES
Exercise 1 · Warm-upPredict the two fallback results

Run the code in your head. Type both output lines in order.

Starter codePop out in the code editor (opens in a new tab)JavaScript
const saved = 0;
console.log(saved || 10);
console.log(saved ?? 10);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeFix a volume default that breaks for 0

    The app should keep a saved volume of 0. Change the defaulting operator.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const savedVolume = 0;
    const volume = savedVolume || 50;
    console.log(volume);

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeRewrite a long guard chain with ?.

      Replace the repeated && checks with optional chaining.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const city = user && user.address && user.address.city;
      console.log(city || "Unknown");

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeAdd defaults with ??=

        Write two logical assignment lines that keep the existing volume but add a theme.

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const settings = { volume: 0 };
        // Fill volume with 50 only if missing.
        // Fill theme with "light" only if missing.
        console.log(settings.volume, settings.theme);

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeSpot the SyntaxError when mixing ?? and ||

          What must you add to make line 4 valid JavaScript?

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          const a = null;
          const b = "backup";
          const c = "last";
          console.log(a || b ?? c);

          Answer, then press Check. Spacing and letter case don’t matter.

            Check your understanding

            7 QUESTIONS
            Nullish and optional chaining quiz · 7 questionsScore: first tries count
            1. Question 1 of 7When does left ?? right use right?

              Choose an answer to see the explanation.

            2. Question 2 of 7What does the count ?? 10 snippet print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const count = 0;
              console.log(count ?? 10);

              Choose an answer to see the explanation.

            3. Question 3 of 7What does the complete user optional chain print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const user = { address: { city: "Pune" } };
              console.log(user?.address?.city);

              Choose an answer to see the explanation.

            4. Question 4 of 7What does the null user fallback print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const user = null;
              console.log(user?.name ?? "Guest");

              Choose an answer to see the explanation.

            5. Question 5 of 7Which line can throw even though it uses ?.?

              Choose an answer to see the explanation.

            6. Question 6 of 7What does the ??= volume snippet print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const settings = { volume: 0 };
              settings.volume ??= 50;
              console.log(settings.volume);

              Choose an answer to see the explanation.

            7. Question 7 of 7Which expression is valid JavaScript?

              Choose an answer to see the explanation.

            Key takeaways

            • ?? falls back only for null and undefined.
            • || falls back for every falsy value, so it can erase 0, false, and blank strings.
            • ?. returns undefined when the link before it is nullish.
            • ?.() skips missing calls, but existing non-functions still throw TypeError.
            • ??=, ||=, and &&= assign only when their matching logical test passes.
            • Parenthesize when mixing ?? with && or ||.

            Final definition: ?? supplies a backup for missing values, and ?. safely stops optional property or call chains at missing links.

            Up next: The rest of the operators.

            CompleteFrontend Clear concepts. Working examples.