Chapter 09 โ€” == vs === (Equality)

๐Ÿ“– Definition

  • == performs loose equality with type coercion.
  • === performs strict equality โ€” no coercion, types must match.

๐Ÿ” Explanation

== tries to make types match before comparing. The rules are notoriously inconsistent, which is why most teams ban == outright (ESLint eqeqeq).

Coercion Rules (==)

  1. If types match โ†’ behave like ===.
  2. null == undefined โ†’ true (special rule).
  3. Number vs string โ†’ string is converted to number.
  4. Boolean โ†’ converted to number (true โ†’ 1, false โ†’ 0).
  5. Object vs primitive โ†’ object is converted via valueOf / toString.

๐Ÿ’ป Code Example โ€” Surprising Coercions

0 == "0";              // true  (string โ†’ number 0)
0 == "";               // true  (empty string โ†’ 0)
0 == false;            // true  (false โ†’ 0)
"" == false;           // true  (both โ†’ 0)

null == undefined;     // true  (special rule)
null == 0;             // false (special exception)

[] == false;           // true   ([] โ†’ "" โ†’ 0; false โ†’ 0)
[1] == 1;              // true   ([1] โ†’ "1" โ†’ 1)
[1, 2] == "1,2";       // true

NaN == NaN;            // false  (NaN never equals anything)
NaN === NaN;           // false

๐Ÿ’ป Code Example โ€” Strict Equality

0 === "0";             // false (different types)
0 === false;           // false
null === undefined;    // false
NaN === NaN;           // false

1 === 1;               // true
"a" === "a";           // true

๐Ÿ’ป Code Example โ€” Object Equality

const a = { x: 1 };
const b = { x: 1 };
const c = a;

a === b;               // false โ€” different references
a === c;               // true  โ€” same reference

// Deep equality requires a helper:
JSON.stringify(a) === JSON.stringify(b);   // true (works for simple shapes)

๐Ÿ’ป Code Example โ€” Checking for NaN

// Wrong:
x === NaN;             // always false

// Right:
Number.isNaN(x);       // ES6, type-safe
isNaN("abc");          // true  (legacy โ€” coerces first)
Number.isNaN("abc");   // false (no coercion)

๐Ÿ’ป Code Example โ€” Object.is

Object.is(NaN, NaN);   // true
Object.is(+0, -0);     // false  (=== returns true)
Object.is(1, 1);       // true

Object.is is the same as === except for NaN and signed zeros.

๐Ÿ’ป Code Example โ€” Safe Null Checks

// Loose check covers both null and undefined
if (value == null) {
  // matches null OR undefined
}

// Strict equivalent
if (value === null || value === undefined) {}

// Modern (preferred)
if (value ?? false) {}             // ?? treats only null/undefined as empty

๐ŸŒ Real-World Impact

  • Always use === unless you specifically want value == null to catch both null and undefined.
  • Add "eqeqeq": "error" to ESLint config.
  • For deep equality, use lodash.isEqual or a library; never roll your own without testing edge cases.

๐ŸŽฏ Likely Interview Questions

  1. Difference between == and ===?
  2. Why is [] == false true? โ€” [] converts via toString โ†’ "" โ†’ number 0. false โ†’ 0. Both equal.
  3. How do you check for NaN? โ€” Number.isNaN(x).
  4. How do you compare two objects for value equality? โ€” JSON.stringify (limited), lodash.isEqual, or a custom deep-equals.

โ† Prototype | Index | Next: Event Handling โ†’