AceDevHub
Control Flow & FunctionsFree

Strict Equality and Comparison

Compare values with ===, Object.is, and relational operators — and know when references matter more than contents.

BeginnerFreeComparison

Comparing values sounds simple until objects, NaN, and API payloads enter the picture. This lesson goes deeper than "use triple equals" — you will understand reference identity, when Object.is beats ===, and why sorting strings with < is not the same as sorting for humans.

Why strict equality is the default

Lesson 5 showed why == coerces types. In production and interviews, === is the baseline: same type and same value, full stop. Special cases still exist — NaN !== NaN, and +0 === -0 even though they behave differently in some math edge cases. null and undefined are different types, so null === undefined is false even though both mean "no useful value" in loose checks.

strict-equality.js
Loading editor…
Outputconsole
true
false
false
true
true
false
false
true

Object.is — SameValue equality

Object.is implements SameValue equality — the spec's notion of "are these interchangeable?" It matches === except NaN equals NaN and +0 does not equal -0. Map keys use SameValueZero (like Object.is but treats +0 and -0 as equal). For everyday app code you may never call Object.is, but libraries comparing cache keys or memoized args rely on these semantics.

Expression===Object.is
NaN, NaNfalsetrue
+0, -0truefalse
1, 1truetrue
"a", "a"truetrue
object-is.js
Loading editor…
Outputconsole
true
false
false
down

Reference equality for objects and arrays

Objects and arrays compare by reference — identity, not shape. Two literals with identical contents are different objects in memory, so === is false. React uses Object.is internally in some paths because referential equality is how it detects "did this state object change?" Shallow equal compares top-level keys; deep equal walks nested structure — choose based on performance and correctness.

reference-equality.js
Loading editor…
Outputconsole
false
true
false
true

Relational operators (<, >, <=, >=)

The example below demonstrates "Relational operators (<, >, <=, >=)" in runnable form. Read the comment lines first — they map each step to the mental model from earlier sections, then trace execution top to bottom as the engine would.

relational.js
Loading editor…
Outputconsole
true
true
true
true
true
false

Safe comparison checklist

Relational operators compare after ToNumeric or lexicographic string rules. String comparison is character-by-character Unicode code unit order — "10" < "9" because "1" < "9", which breaks naive sorting of numeric strings. For user-visible sorting use localeCompare with locale and numeric options. Mixing types in < and > triggers coercion; avoid it.

  • Same primitive type? Use ===
  • Need to detect NaN? Use Number.isNaN(x)
  • Compare object contents? Use deep/shallow helper or serialize
  • Sort strings for users? Use localeCompare, not <
  • Never compare unrelated types without explicit conversion

Production codebases standardize on === and explicit conversion helpers (Number(), String()) at system boundaries. Code review should flag == unless there is a documented legacy reason. Pair strict equality with lint rules like eqeqeq so mistakes never reach main.

  1. 1=== compares type and value; null and undefined are distinct
  2. 2Object.is handles NaN and signed zero where === fails
  3. 3Objects/arrays equal only when references match
  4. 4Next lesson: if/else, switch, and ternary control flow