Detailed explanation
Optional chaining (`?.`) and nullish coalescing (`??`) are JavaScript operators for handling missing values without treating every falsy value as missing. A nullish value is specifically `null` or `undefined`; values such as `0`, `false`, `''`, and `NaN` are not nullish. These operators are useful when reading API responses, optional configuration, or nested objects whose fields may be absent. Together, they make defensive code shorter while preserving meaningful values that a truthiness check would accidentally discard.
Optional chaining checks the value immediately before an optional access. If that value is nullish, evaluation short-circuits and the continuous chain produces `undefined`; otherwise, normal property access or invocation proceeds. For example, `user?.address?.city` safely handles a missing user or address. However, `user?.address.city` can still throw if user exists but address is nullish. Supported forms include property access, `obj?.name`, computed access, `obj?.[key]`, and optional calls, `callback?.()`. Skipped expressions are not evaluated: in `obj?.[index++]`, index is not incremented when obj is nullish. Optional chaining is not general exception handling: an undeclared root identifier still causes a `ReferenceError`, and calling an existing non-function still causes a `TypeError`.
Nullish coalescing selects a fallback only when its left operand is nullish. Thus, `const port = cfg.port ?? 3000` preserves an explicitly configured zero, while `cfg.port || 3000` replaces zero because logical OR uses truthiness. The right operand is evaluated only if needed, so `value ?? computeDefault()` avoids calling computeDefault when value is present. Note that this example assumes cfg itself exists; use `cfg?.port ?? 3000` when cfg may also be nullish.
Interviewers typically check whether you understand the distinction between absence and falsiness, plus where short-circuiting stops. Grouping can break a continuous optional chain: `(user?.address).city` can throw. Also, JavaScript forbids mixing `??` directly with `||` or `&&` without parentheses; write `(a || b) ?? c` to state the intended grouping. Use these operators for genuinely optional data, not to silently hide violations of required data contracts.
Key points to remember
- `?.` short-circuits to `undefined` when the value being checked is `null` or `undefined`.
- `??` supplies a default only for nullish values, preserving `0`, `false`, and empty strings.
- Optional chaining supports property access, computed access, and optional function calls.
- Both operators short-circuit, so skipped keys, arguments, or fallback expressions are not evaluated.
- Combine them as `user?.address?.city ?? 'Unknown'` for safe access with a default.
Common mistakes candidates make
- Using `||` for defaults when zero, false, or an empty string is a valid input.
- Assuming one `?.` protects every nullable link, undeclared variables, or calls to non-functions.
- Breaking an optional chain with grouping, or mixing `??` with `||` or `&&` without required parentheses.
Likely follow-up questions
What is the difference between `obj?.method()` and `obj.method?.()`?
`obj?.method()` skips the call when obj is nullish, but throws if obj exists and method is missing or not callable. `obj.method?.()` requires obj to exist but skips a nullish method; `obj?.method?.()` checks both.
Can optional chaining be used on the left side of an assignment?
No, `obj?.name = 'Asha'` is invalid JavaScript syntax. Check that obj is not nullish before assigning to its property.
Does nullish coalescing replace `NaN` or an empty string?
No, `NaN ?? 10` evaluates to `NaN`, and `'' ?? 'default'` evaluates to the empty string. If those values are invalid for your application, validate them explicitly rather than treating them as nullish.
Interview tip: Define nullish values first, contrast `0 ?? 3000` with `0 || 3000`, and finish with a combined optional-access and fallback example.
