Skip to main content

What is the Difference Between == and ===?

Answer

== (loose equality) compares values after type coercion, while === (strict equality) compares both value AND type without coercion.

Quick Comparison

Examples

// Strict equality (===)
console.log(5 === 5); // true
console.log(5 === "5"); // false (different types)
console.log(true === 1); // false (different types)
console.log(null === undefined); // false

// Loose equality (==)
console.log(5 == 5); // true
console.log(5 == "5"); // true (string converted to number)
console.log(true == 1); // true (boolean converted to number)
console.log(null == undefined); // true (special case)

Type Coercion Rules for ==

// String vs Number → String converted to Number
console.log("42" == 42); // true

// Boolean vs anything → Boolean converted to Number first
console.log(true == 1); // true (true → 1)
console.log(false == 0); // true (false → 0)
console.log(true == "1"); // true (true → 1, "1" → 1)

// null and undefined
console.log(null == undefined); // true (special case)
console.log(null == 0); // false
console.log(undefined == 0); // false

// Object vs Primitive → Object converted to primitive
console.log([1] == 1); // true ([1].toString() → "1" → 1)
console.log([1, 2] == "1,2"); // true ([1,2].toString() → "1,2")

Surprising Results with ==

// Empty string
console.log("" == false); // true (both become 0)
console.log("" == 0); // true

// Arrays
console.log([] == false); // true ([] → "" → 0, false → 0)
console.log([] == 0); // true
console.log([] == ""); // true

// Objects
console.log({} == false); // false
console.log({} == "[object Object]"); // true

// NaN
console.log(NaN == NaN); // false (NaN is never equal to anything)
console.log(NaN === NaN); // false

Best Practice: Always Use ===

// ✅ Good: Explicit and predictable
if (value === null) {
}
if (count === 0) {
}
if (name === "") {
}

// ❌ Avoid: Implicit coercion can cause bugs
if (value == null) {
} // Matches both null AND undefined
if (count == 0) {
} // Matches 0, "", false, null, undefined
if (name == "") {
} // Matches "", 0, false

// Exception: Check for null OR undefined
if (value == null) {
// This is intentional to catch both null and undefined
}
// Modern alternative:
if (value === null || value === undefined) {
}
// Or:
if (value ?? true === true) {
}

Inequality Operators

// !== (strict inequality)
console.log(5 !== "5"); // true (different types)
console.log(5 !== 5); // false

// != (loose inequality)
console.log(5 != "5"); // false (after coercion, they're equal)
console.log(5 != 6); // true

Object Comparison

// Objects are compared by reference, not value
const obj1 = { a: 1 };
const obj2 = { a: 1 };
const obj3 = obj1;

console.log(obj1 === obj2); // false (different references)
console.log(obj1 === obj3); // true (same reference)
console.log(obj1 == obj2); // false (still by reference)

// Same for arrays
console.log([1, 2] === [1, 2]); // false
console.log([1, 2] == [1, 2]); // false

Coercion Table

xyx == yx === y
55truetrue
5"5"truefalse
0falsetruefalse
""falsetruefalse
nullundefinedtruefalse
[]falsetruefalse
NaNNaNfalsefalse
{}{}falsefalse

Key Points

  • === checks type AND value (recommended)
  • == converts types before comparing
  • Objects are compared by reference
  • NaN is not equal to anything, including itself
  • Use Object.is() for edge cases like NaN
  • Best practice: Always use === and !==