Conditionals & Operators (??, ?.)

Every interesting program makes decisions : show this if logged in, charge that if the cart isn't empty, fall back to a default when data is missing. Modern JavaScript gives you elegant tools for all of it — the ternary, nullish coalescing ?? , and optional chaining ?. .

Learn Conditionals & Operators (??, ?.) in our free JavaScript course — a beginner-friendly interactive lesson with runnable examples, a practice exercise…

Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

These operators replace whole blocks of defensive if statements with a single clear line.

🚦 Real-World Analogy: Conditionals are the traffic lights of your code:

The workhorse of decision-making. Conditions are checked top to bottom; the first truthy one wins and the rest are skipped.

Comparisons produce booleans; logical operators combine them. Always prefer === over == (you'll see exactly why in the Type Coercion lesson).

condition ? valueIfTrue : valueIfFalse picks between two values in a single expression. It's ideal for assignments and inline labels:

?? returns the right side only when the left is null or undefined . This is crucial when 0 , "" , or false are legitimate values that || would wrongly discard:

(The blank line is the empty string printed by name ?? "Guest" .)

Reaching into nested data that might be missing used to need a wall of && guards. ?. does it in one operator, returning undefined the moment something is nullish:

switch compares one value against many constant cases. && and || short-circuit, returning an operand rather than a strict boolean — handy for conditional actions:

These lines should safely read a user's city and fall back to "Unknown" , then print a greeting. They are scrambled — reorder them.

Why: the object (B) must exist before you read from it (A). Because user has no address , optional chaining returns undefined and ?? supplies "Unknown" — without ?. this line would throw. isLocal (D) depends on city , and the ternary (C) depends on isLocal , so the final log (E) reads: Welcome, Mia from Unknown .

0 then fallback . ?? only replaces null / undefined , so 0 ?? "fallback" keeps 0 . || replaces any falsy value, and 0 is falsy, so it returns "fallback" .

undefined — obj.x is undefined , so optional chaining short-circuits the whole expression to undefined instead of throwing a TypeError when trying to read .y .

done — && returns the first falsy operand or, if all are truthy, the last one. All three values are truthy, so it returns the final value "done" .

Up next: Type Coercion — why == surprises everyone and how to stay safe! ⚖️

Practice quiz

In an if / else if / else chain, which block runs?

  • The first block whose condition is truthy
  • Every block whose condition is truthy
  • The last block whose condition is truthy
  • Only the else block

Answer: The first block whose condition is truthy. Conditions are checked top to bottom; the first truthy one runs and the rest are skipped.

What does console.log(0 ?? 10) output?

  • 10
  • 0
  • undefined
  • null

Answer: 0. ?? only falls back when the left side is null or undefined; 0 is neither, so it is kept.

What does console.log(0 || 10) output?

  • 0
  • 10
  • true
  • false

Answer: 10. || falls back on ANY falsy value, and 0 is falsy, so it returns 10.

The ternary operator follows which syntax?

  • condition ? valueIfTrue : valueIfFalse
  • condition : valueIfTrue ? valueIfFalse
  • if condition then a else b
  • condition ?? a : b

Answer: condition ? valueIfTrue : valueIfFalse. A ternary is written condition ? valueIfTrue : valueIfFalse and picks one value in a single expression.

Given const user = { name: 'Ada' }; what does console.log(user.contact?.email) output?

  • TypeError
  • null
  • undefined
  • ''

Answer: undefined. Optional chaining short-circuits to undefined the moment user.contact is undefined, instead of throwing.

What does console.log('hi' && 42 && 'done') log?

  • true
  • hi
  • 42
  • done

Answer: done. && returns the first falsy operand, or the last value if all are truthy; here all are truthy so it returns 'done'.

What does console.log(0 && 'skipped') output?

  • 0
  • skipped
  • false
  • undefined

Answer: 0. && returns the first falsy operand, and 0 is falsy, so it short-circuits and returns 0.

Why prefer ?? over || when 0 or '' are valid values?

  • ?? is faster than ||
  • || replaces any falsy value, wrongly discarding a valid 0 or ''
  • ?? only works on numbers
  • || throws on null

Answer: || replaces any falsy value, wrongly discarding a valid 0 or ''. || falls back on every falsy value, so a legitimate 0 or '' gets discarded; ?? only falls back on null/undefined.

Given const data = { items: ['a', 'b'] }; what does console.log(data.items?.[0]) output?

  • undefined
  • a
  • a
  • b

Answer: a. Optional chaining also works for array access; items exists, so ?.[0] reads the first element 'a'.

In a switch statement, what happens if you forget break (or return) in a case?

  • A SyntaxError is thrown
  • Execution falls through to the next case
  • Only the default runs
  • The switch is skipped entirely

Answer: Execution falls through to the next case. Without break or return, execution falls through and runs the following case(s) too.