Output Questions: Coercion, Operators & Equality

Predict the output โ€” type coercion puzzles, == vs ===, + operator surprises, typeof edge cases, and bitwise/logical traps.

must hard โฑ 25 min coercionoperatorsequalitytypeofNaNspreaddestructuring
Mastery:
Why interviewers ask this
Type coercion questions appear in every phone screen because they quickly reveal JS depth. The surprising answers are precisely what interviewers look for.

Q1 โ€” the + operator with mixed types

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"12"
2
"33"
"123"
3
1
0
NaN
0
NaN
  • + prefers concatenation when either operand is a string.
  • - always converts to numbers (no string subtraction).
  • 1 + 2 + '3' โ†’ left to right: 3 + '3' โ†’ '33'.
  • '1' + 2 + 3 โ†’ '12' + 3 โ†’ '123'.
  • Unary + calls ToNumber: +true = 1, +null = 0, +undefined = NaN, +[] = +'' = 0, +{} = NaN.

Q2 โ€” loose equality zoo

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
true
true
false
true
false
false
false
true
true
  • 0 == false โ†’ both โ†’ 0 == 0 โ†’ true
  • '' == false โ†’ '' == 0 โ†’ 0 == 0 โ†’ true
  • null == false โ†’ false โ€” null only equals undefined with ==, nothing else.
  • null == undefined โ†’ true โ€” special rule.
  • null == 0 โ†’ false โ€” nullโ€™s only == partner is undefined.
  • NaN == NaN โ†’ false โ€” NaN is never equal to anything including itself.
  • [] == false โ†’ '' == false โ†’ 0 == 0 โ†’ true
  • [] == ![] โ†’ [] == false โ†’ (above) โ†’ true

Q3 โ€” typeof gotchas

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"object"
"undefined"
"number"
"object"
"object"
"function"
"string"
"undefined"
  • typeof null โ†’ 'object' โ€” historical bug, never fixed.
  • typeof NaN โ†’ 'number' โ€” NaN is the โ€œNot a Numberโ€ number.
  • Arrays and objects both โ†’ 'object'.
  • Functions โ†’ 'function' (special case).
  • typeof typeof 1 โ†’ typeof 'number' โ†’ 'string'.
  • typeof undeclaredVar โ†’ 'undefined' (not a ReferenceError โ€” typeof is safe).

Q4 โ€” increment/decrement operators

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
5
6
7
7
6
  • a++ (post-increment) โ€” returns current value then increments: returns 5, a becomes 6.
  • ++a (pre-increment) โ€” increments then returns: a becomes 7, returns 7.
  • a-- (post-decrement) โ€” returns current value 7, then decrements to 6.

Q5 โ€” short-circuit evaluation

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"default"
"fallback"
"ok"
1
0
"yes"
"fallback"
0
false
  • || returns the first truthy value (or the last value if all falsy).
  • && returns the first falsy value (or the last value if all truthy).
  • ?? (nullish coalescing) โ€” only falls through on null or undefined (not 0, '', false). This is the key difference from ||.

Q6 โ€” [] + [] and [] +

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
""
"[object Object]"
"[object Object]"
  • [] + [] โ†’ '' + '' โ†’ '' (both arrays convert to empty strings).
  • [] + {} โ†’ '' + '[object Object]' โ†’ '[object Object]'.
  • {} + [] in a statement context โ€” {} is parsed as an empty block, then +[] is the expression โ†’ +'' = 0. But ({}) + [] forces {} to be an object expression โ†’ '[object Object]'.

Q7 โ€” truthy/falsy surprises

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
(logs truthy values: "0", [], {}, Infinity, -Infinity)
truthy count: 5

Falsy: 0, -0, '', false, null, undefined, NaN โ€” 7 values. Everything else is truthy, including "0" (non-empty string), [] (empty array), {} (empty object), Infinity, -Infinity.


Q8 โ€” comparison oddities

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
false
false
true
false
false
false

This is the most counterintuitive coercion result. For >, <, >=, <=, null converts to 0. So null >= 0 โ†’ 0 >= 0 โ†’ true. But == has special rules โ€” null only equals undefined. So null == 0 is false even though null >= 0 is true. This inconsistency is a known JS quirk.

undefined converts to NaN for comparisons โ†’ any comparison with NaN is false. And undefined == 0 is false (only null == undefined).


Q9 โ€” destructuring output

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
1 2 [3, 4, 5]
5 20 30
2 4
  • Rest element collects remaining items into an array.
  • y = 20 โ€” default values apply only when the property is undefined. y is not in the source โ†’ 20.
  • x = 10 โ€” x IS in the source (5), so the default is ignored: 5.
  • z โ€” present in source as 30.
  • [, second, , fourth] โ€” skip positions with empty slots.

Q10 โ€” spread edge cases

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
[1, 2, 3]
[1, 2, 3, 4]
99

Array spread creates a shallow copy โ€” b is a new array, pushing to it doesnโ€™t affect a. Object spread is also shallow โ€” copy.nested and obj.nested point to the same object. Mutating copy.nested.y mutates obj.nested.y too.


Q11 โ€” optional chaining and nullish

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"Alice"
undefined
undefined
18
"Alice"
  • ?. short-circuits to undefined when it hits null or undefined without throwing.
  • address?.city โ€” address is null, so null?.city โ†’ undefined (no error).
  • settings doesnโ€™t exist โ†’ undefined, then ?.theme โ†’ undefined.
  • ?? 18 โ€” age is undefined, so nullish coalescing returns 18.
  • name ?? 'Anonymous' โ€” name is 'Alice' (not nullish) โ†’ 'Alice'.

Q12 โ€” comma operator and void

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
3
undefined
undefined
1 9
  • The comma operator evaluates each operand left-to-right and returns the value of the last one. (1, 2, 3) โ†’ 3.
  • void expression always evaluates the expression and returns undefined. Common use: void 0 as a reliable undefined.
  • In for (let i = 0, j = 10; ...), the comma in the init and update sections is part of the for syntax (initializes/updates multiple variables), not the comma operator.

The coercion short list
+ string-wins. -/*// always ToNumber. == coerces โ€” null only equals undefined, NaN equals nothing. ?? is null-or-undefined only (not falsy). ||/&& return operands, not booleans. typeof null === โ€˜objectโ€™ (bug). typeof undeclared === โ€˜undefinedโ€™ (safe). Spread is shallow โ€” nested objects still share references.

Likely follow-up questions
  • What does + do when one operand is a string?
  • Why is [] + [] an empty string?
  • Why is [] + {} '[object Object]' but {} + [] is 0?
  • What is the double negation !! trick?
  • What is the nullish coalescing operator?

References