Coercion & Operators
Type and boolean coercion, loose vs strict equality, and the operator families — logical, bitwise, unary.
10 questions
MiddleTheoryVery commonWhat is the difference between == and ===?
What is the difference between == and ===?
=== (strict) compares value and type with no conversion, so different types are never equal. == (loose) coerces operands to a common type first, so 0 == '', 1 == '1', and null == undefined are all true. NaN is never equal to anything, and +0 === -0 is true.
Common mistakes
- ✗Believing
===performs coercion — it never converts types - ✗Thinking
NaN === NaNistrue - ✗Assuming
==compares object contents rather than reference
Follow-up questions
- →Walk through how
==coerces both sides in[] == ![]. - →Why is
+0 === -0true butObject.is(+0, -0)false?
MiddleTheoryVery commonWhat value do &&, ||, and ?? return, and how do they short-circuit?
What value do &&, ||, and ?? return, and how do they short-circuit?
These operators short-circuit and return one of their operands, not a coerced boolean. && returns the first falsy operand or the last if all are truthy. || returns the first truthy operand or the last otherwise. ?? returns the right side only when the left is null or undefined, ignoring other falsy values. So 0 || 'x' is 'x' but 0 ?? 'x' is 0.
Common mistakes
- ✗Assuming the operators return a boolean rather than one of the operands
- ✗Treating
??like||, forgetting it only checksnull/undefined - ✗Thinking both sides always evaluate, missing short-circuit skipping
Follow-up questions
- →What does
'' && 'x'return, and why does short-circuiting stop early? - →When would
??and||give different results for the same left operand?
JuniorTheoryCommonWhat is implicit type coercion in JavaScript?
What is implicit type coercion in JavaScript?
Implicit coercion is JavaScript automatically converting an operand to another type to complete an operation. + with a string converts the other side to a string (1 + '2' is '12'); other arithmetic and comparisons convert toward numbers ('3' * 2 is 6). Boolean contexts coerce values to truthy or falsy.
Common mistakes
- ✗Assuming
+is always numeric — with a string operand it concatenates - ✗Thinking
===performs coercion (it never does) - ✗Expecting coercion to throw on a type mismatch instead of silently converting
Follow-up questions
- →Why does
1 + '2'give'12'but'3' * 2give6? - →What is the difference between
Number(x)and the unary+x?
JuniorTheoryCommonWhich values are falsy in JavaScript, and what does !!x do?
Which values are falsy in JavaScript, and what does !!x do?
The 8 falsy values are false, 0, -0, 0n, '', null, undefined, and NaN; everything else is truthy, including '0', [], and {}. !!x applies logical NOT twice, coercing any value to its boolean equivalent — true if truthy, false if falsy.
Common mistakes
- ✗Thinking
'0',[], or{}are falsy — they are all truthy - ✗Forgetting
NaN,-0, and0nare falsy - ✗Believing
!!xreturns the value rather than a boolean
Follow-up questions
- →Why is an empty array
[]truthy even though[] == falseistrue? - →How does
!!xdiffer fromBoolean(x)?
JuniorTheoryOccasionalWhat are the main categories of operators in JavaScript?
What are the main categories of operators in JavaScript?
JavaScript groups operators by purpose: arithmetic (+ - * / % **), comparison (< > == ===), logical (&& || ! ??), bitwise (& | ^ ~ << >>), assignment (= += &&=), the ternary ?:, and the comma operator. Operators also differ by arity: most are binary, but ! and typeof are unary and ?: is ternary.
Common mistakes
- ✗Thinking
?:is just syntax forifrather than an operator that yields a value - ✗Assuming logical operators always return a boolean rather than one of their operands
- ✗Believing JavaScript has no bitwise operators because numbers are floating-point
Follow-up questions
- →What is the arity of
?:, and why is that significant? - →Which category does
??belong to, and how does it differ from||?
JuniorTheoryOccasionalWhat are the unary operators in JavaScript and what does each do?
What are the unary operators in JavaScript and what does each do?
A unary operator takes one operand. typeof x returns a type string like number. delete obj.k removes an own property. void expr evaluates expr and returns undefined. !x coerces to boolean and negates it. Unary +x converts to number (+'5' is 5), and unary -x negates numerically. ++/-- increment or decrement in place.
Common mistakes
- ✗Thinking
deletefrees a variable or memory rather than removing an own property - ✗Expecting
voidto returnnullinstead of alwaysundefined - ✗Forgetting unary
+/-coerce to number, so+'5'is5not'5'
Follow-up questions
- →What does
deletereturn when you try to remove a non-configurable property? - →Why is
void 0sometimes used as a safe way to produceundefined?
MiddleTheoryOccasionalHow do the ternary ?: and the comma operator each work in JavaScript?
How do the ternary ?: and the comma operator each work in JavaScript?
The ternary cond ? a : b is the only three-operand operator: it evaluates cond, then returns a if truthy or b otherwise, and it is an expression that yields a value. The comma operator a, b, c evaluates every operand left to right but returns only the value of the last one, so (1, 2, 3) is 3. The middle operands run for their side effects.
Common mistakes
- ✗Thinking
?:is a statement, not an expression that returns a value - ✗Believing the comma operator returns the first operand instead of the last
- ✗Forgetting the ternary only evaluates the branch it selects
Follow-up questions
- →How does the comma operator let a
forloop update two variables at once? - →Why can you nest ternaries, and when does that hurt readability?
SeniorTheoryOccasionalHow does loose equality coerce its operands? Walk through [] == ![].
How does loose equality coerce its operands? Walk through [] == ![].
== follows the Abstract Equality steps: null == undefined is special-cased to true; a number-versus-string comparison coerces the string to a number; a boolean operand converts to a number first; and an object-versus-primitive comparison converts the object via ToPrimitive. For [] == ![]: ![] is false then 0; [] becomes '' then 0; so 0 == 0 is true.
Common mistakes
- ✗Comparing the two sides' truthiness directly instead of following the coercion steps
- ✗Forgetting a boolean operand converts to a number before comparison
- ✗Assuming an object compares by its JSON form rather than via
ToPrimitive
Follow-up questions
- →Why does
[] == ''hold but[] === ''does not? - →How does
ToPrimitivechoose between an object'svalueOfandtoString?
SeniorTheoryOccasionalHow do operator precedence and associativity decide evaluation order in JavaScript?
How do operator precedence and associativity decide evaluation order in JavaScript?
Precedence decides which operator binds tighter when expressions lack parentheses, so * runs before + in 1 + 2 * 3. Associativity breaks ties among same-precedence operators: most are left-associative, but =, **, and ?: are right-associative. Precedence only controls grouping, not the left-to-right order in which operands are evaluated. Common traps include ** over unary - and && binding tighter than ||.
Common mistakes
- ✗Confusing precedence (grouping) with operand evaluation order (still left-to-right)
- ✗Assuming
=,**, and?:are left-associative like most operators - ✗Forgetting
&&binds tighter than||, changing how conditions group
Follow-up questions
- →Why is
-2 ** 2a syntax error, and how do you write it correctly? - →How does right-associativity make
a = b = cassign from the right?
MiddleTheoryRareWhat bitwise operators does JavaScript have, and what does the ~~ trick do?
What bitwise operators does JavaScript have, and what does the ~~ trick do?
Bitwise operators are & (AND), | (OR), ^ (XOR), ~ (NOT), << (left shift), >> (sign-propagating right shift), and >>> (zero-fill right shift). They first convert operands to 32-bit signed integers, so they discard the fractional part. Double NOT ~~x therefore truncates toward zero like Math.trunc, e.g. ~~4.9 is 4 and ~~-4.9 is -4.
Common mistakes
- ✗Forgetting bitwise ops first coerce operands to 32-bit signed integers
- ✗Confusing
~~x(truncation) with rounding likeMath.round - ✗Treating
>>and>>>as identical, ignoring sign handling
Follow-up questions
- →Why does
~~xfail to truncate numbers larger than 2³¹−1 correctly? - →How does
>>>differ from>>when the operand is negative?