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.