JavaScript: Double Equals (==) vs. Triple Equals (===)
One of the most classic JavaScript interview questions is:
What is the difference between double equals (==) and triple equals (===) in JavaScript?
Every junior developer learns that == compares values and === compares both value and type. But interviewers want to test if you understand type coercion mechanics under the hood:
- Implicit Type Coercion: How JavaScript automatically converts values during loose comparison.
- Comparison Algorithm: The rules JavaScript uses to match values (like string-to-number or boolean-to-number).
- Falsy Pitfalls: Why statements like
[] == falseor"" == 0evaluate totrue. - Exceptions: How special values like
NaN,null, andundefinedbehave in comparisons.
Let's explore JavaScript's equality operators from first principles.
1. Loose Equality (==) with Coercion
The loose equality operator (==) compares two values for equality after converting both values to a common type. This process is known as implicit type coercion.
When comparing variables of different types with ==:
- If one is a Boolean, it is converted to a Number (
truebecomes1,falsebecomes0). - If comparing a String and a Number, the string is coerced to a number (
Number(string)). - If one is an Object and the other is a Primitive, the object is converted to a primitive using its
valueOf()ortoString()methods.
console.log(5 == "5"); // true (String "5" is coerced to number 5)
console.log(1 == true); // true (Boolean true is coerced to number 1)
console.log(0 == false); // true (Boolean false is coerced to number 0)2. Strict Equality (===)
The strict equality operator (===) compares two values for equality without performing type coercion.
For strict comparison to return true:
- Both values must have the exact same type.
- Both values must have the exact same value (or point to the same memory reference for objects).
console.log(5 === "5"); // false (Number vs String)
console.log(1 === true); // false (Number vs Boolean)
console.log(5 === 5); // true3. Falsy Comparison Pitfalls
Loose equality coercion rules lead to highly unintuitive comparisons that senior developers must avoid:
console.log("" == 0); // true (Empty string converts to number 0)
console.log([] == false); // true (Array converts to empty string "", which converts to 0)
console.log(null == 0); // false (special case: null only equals undefined loosely)The Null & Undefined Exception
Under the loose equality algorithm, null and undefined are loosely equal to each other but are not coerced to any other values (like false or 0).
console.log(null == undefined); // true
console.log(null === undefined); // false (different types)4. Summary Table
| Comparison | Loose Equality (==) | Strict Equality (===) |
|---|---|---|
5 == "5" | ✅ true | ❌ false |
0 == false | ✅ true | ❌ false |
null == undefined | ✅ true | ❌ false |
NaN == NaN | ❌ false (NaN never equals itself) | ❌ false |
[] == "" | ✅ true | ❌ false |
Senior-Level Interview Answer
Double equals (
==) compares values after performing implicit type coercion, trying to convert both operands to a matching primitive type (usually numeric). Triple equals (===) compares both the value and the type strictly, returning false if types do not align. For example,5 == "5"evaluates to true because the string is coerced to a number, whereas5 === "5"is false due to type mismatch. Because loose coercion rules lead to unintuitive behaviors (like[] == falseevaluating to true), strict equality (===) is the industry standard for code predictability, with double equals reserved almost exclusively for checking if a value is null or undefined simultaneously (val == null).
Common Interview Mistakes
❌ Relying on == to check for falsy values
Using if (value == false) can lead to logic bugs if value is an empty array [] or the number 0, which are coerced to false loosely. Instead, write explicit checks or use boolean casting: if (!value).
❌ Thinking NaN can be compared using equality operators
NaN (Not-a-Number) is the only value in JavaScript that is not equal to itself under either == or ===. To check for NaN, use Number.isNaN(value).
console.log(NaN === NaN); // false
console.log(Number.isNaN(NaN)); // trueKey Takeaways
- Loose Equality: Double equals (
==) performs implicit type coercion, converting operands to numeric primitives before comparison. - Strict Equality: Triple equals (
===) enforces strict type matching, guaranteeing both type and value are identical. - Null and Undefined:
null == undefinedis true, which provides a convenient way to check for both null or empty values. - NaN Behavior:
NaNis not equal to itself under either operator; you must useNumber.isNaN()to identify it. - Best Practice: Use triple equals (
===) by default to avoid coercion bugs and ensure runtime predictability.