Equality, Coercion & Comparison Traps
Key Learning Objectives
Master the 4 ECMAScript equality algorithms: isLooselyEqual (==), isStrictlyEqual (===), SameValueZero, and SameValue (Object.is).
Understand why null >= 0 is true while null == 0 is false and null > 0 is false.
Learn the mechanics of relational string comparisons (lexicographical character code order).
Understand Object.is() edge cases: differentiating +0 and -0, and evaluating NaN equality.
Avoid truthiness and coercion traps with empty arrays, zeros, and boolean coercion in interview code puzzles.
The Interview Problem
What is logged to the console when the following equality and relational comparisons execute, and why do loose equality and relational operators handle null and arrays with fundamentally different rules?
1const c1 = null >= 0;2const c2 = null == 0;3const c3 = '12' < '9';4const c4 = Object.is(NaN, NaN);5const c5 = Object.is(+0, -0);6const c6 = [0] == false;78console.log(c1, c2, c3, c4, c5, c6);
Predict Console Output
Select the option that matches what standard ECMAScript prints to the console:
true false true true false true
false false false false true false
true true true true false true
true false false true true false
V8 Engine Execution Trace
Step 1 of 7 (Line 1)Relational operator >= triggers ToNumber on null, yielding 0. Evaluates 0 >= 0, returning true.
Deep Technical Breakdown
The Four Equality Algorithms in ECMAScript
JavaScript defines four distinct equality mechanisms in the standard specification:
- Abstract Equality (
==): Coerces types if operands are different types (e.g. string to number, object to primitive via[Symbol.toPrimitive]('default')/valueOf()/toString()). - Strict Equality (
===): Returnsfalseimmediately if types differ. Exceptions:NaN === NaNisfalse, and+0 === -0istrue. SameValueZero: Used internally byMap,Set, andArray.prototype.includes(). TreatsNaNas equal toNaN, and+0as equal to-0.SameValue(Object.is()): Distinguishes+0from-0(evaluates tofalse), and treatsNaNas equal toNaN(evaluates totrue).
The Great null Comparison Paradox
Candidates are frequently stumped by this classic interview trio:
null > 0; // false
null == 0; // false
null >= 0; // true!Why does this happen?
- For
>and<: The engine runsToNumber(null), which returns0. It then tests0 > 0, which isfalse. - For
==: The engine does NOT runToNumber. Step 2 & 3 of the Abstract Equality Comparison rule state: If Type(x) is Null and Type(y) is Undefined, return true (and vice versa). Null is never coerced to a number in==. Therefore,null == 0isfalse. - For
>=: In JavaScript,a >= bis formally defined as!(a < b). The engine testsnull < 0:ToNumber(null)is0, so0 < 0isfalse. Negatingfalseyieldstrue!
Lexicographical String Comparisons
If both operands to <, <=, >, >= are strings, no numeric coercion happens:
'12' < '9'; // true, because '1' (code 49) < '9' (code 57)
'apple' < 'banana'; // trueHowever, if one operand is a number, the string is coerced to a number:
'12' < 9; // false, because Number('12') is 12, and 12 < 9 is falsePolyfill: Object.is
function objectIs(x, y) {
if (x === y) {
// Differentiate +0 from -0: 1 / +0 is +Infinity, while 1 / -0 is -Infinity!
return x !== 0 || 1 / x === 1 / y;
}
// Differentiate NaN: NaN is the only value in JavaScript not equal to itself
return x !== x && y !== y;
}Common Traps & Mistakes
Assuming `null == 0` is true because `null >= 0` is true. `==` never coerces null to number 0.
Assuming `'12' < '9'` evaluates numerically to false. String relational comparisons compare ASCII/Unicode character values.
Using `===` to check if a value is `NaN`. Always use `Number.isNaN(val)` or `Object.is(val, NaN)`.
Confusing `[0] == false` (true due to coercion) with `Boolean([0])` (truthy because all objects and arrays are truthy).
FAANG Follow-Up Probes
Probe #1
How does Array.prototype.indexOf differ from Array.prototype.includes when searching for NaN in an array?
Probe #2
Why does [] == ![] evaluate to true in JavaScript?
Probe #3
How does the ToPrimitive algorithm prioritize [Symbol.toPrimitive], valueOf(), and toString() during coercion?
