JavaScript Comparison Operators: Double vs Triple Equals
== and === both compare values, but only one is safe. Learn how type coercion works with ==, why === is the better default, and the few cases where == is acceptable.
JavaScript double equals (==) and triple equals (===) both compare two values, but they behave very differently. Strict equality checks whether two values are the same without converting anything. Loose equality tries to convert the values to the same type before comparing, which can produce surprising results.
console.log(0 === false); // false (number vs boolean, no match)
console.log(0 == false); // true (false is converted to 0, then 0 == 0)This single example explains why strict equality is the safer default.
How === (Strict Equality) Works
Strict equality checks two things: the value and the type. If the types are different, it returns false immediately without trying to convert anything:
console.log(5 === 5); // true (same type, same value)
console.log(5 === "5"); // false (number vs string, no conversion)
console.log(true === 1); // false (boolean vs number)
console.log(null === undefined); // false (different types)
console.log(0 === false); // false (number vs boolean)Strict equality is predictable. Every comparison in the example above behaves exactly as you would expect from looking at the types.
How == (Loose Equality) Works
Loose equality tries to convert both values to the same type before comparing. This process is called type coercion:
console.log(5 == "5"); // true (string "5" becomes number 5)
console.log(true == 1); // true (true becomes 1)
console.log(false == 0); // true (false becomes 0)
console.log(null == undefined); // true (special rule for null/undefined)
console.log("" == 0); // true (empty string becomes 0)
console.log([] == 0); // true (empty array becomes "" then 0)
console.log([] == ""); // true (empty array becomes "")Each of these results follows coercion rules, but most developers find them surprising on first encounter. The rules are consistent, but they are not intuitive.
The Coercion Rules for ==
When you use loose equality, JavaScript follows these steps:
The algorithm tries to coerce values into matching types, step by step, until it can make a comparison. This chain of conversions is what produces the unexpected results.
The == Surprises Table
| Expression | Result | Why |
|---|---|---|
| 0 == false | true | false becomes 0, then 0 == 0 |
| "" == false | true | Both become 0 |
| "" == 0 | true | "" becomes 0 |
| "0" == false | true | Both become 0 |
| whitespace string == 0 | true | Whitespace string becomes 0 |
| [] == 0 | true | [] becomes "" then 0 |
| [1] == 1 | true | [1] becomes "1" then 1 |
| [1,2] == "1,2" | true | Array becomes comma-separated string |
| null == 0 | false | null only equals null and undefined |
| undefined == 0 | false | undefined only equals null and undefined |
If this table makes you uncomfortable, that is the right reaction. Most of these results are consequences of coercion rules, not expressions anyone would intentionally write. With strict equality, every expression in the table except direct value matches would return false.
The One Case for ==
There is one idiomatic use of loose equality that is widely accepted: checking for both null and undefined at once:
if (value == null) {
// value is either null or undefined
}This is equivalent to the more explicit strict version below, which spells out both checks instead of relying on the special loose-equality rule:
if (value === null || value === undefined) {
// same check, more verbose
}Because null == undefined is true (a special rule in the spec) and neither equals anything else with loose equality, value == null is a clean shorthand. For all other comparisons, use strict equality.
Strict Inequality: !== vs !=
The same rules apply to inequality. !== is the strict version, and != is the loose version:
console.log(5 !== "5"); // true (strict: different types, so they are not equal)
console.log(5 != "5"); // false (loose: "5" becomes 5, then 5 == 5)Always prefer strict inequality for the same reasons you prefer strict equality.
Object and Array Comparisons
Both loose and strict equality compare objects and arrays by reference, not by content:
console.log({} === {}); // false (different objects in memory)
console.log([] === []); // false (different arrays in memory)
console.log({} == {}); // false (same rule applies to ==)
console.log([] == []); // false
const a = [1, 2, 3];
const b = a;
console.log(a === b); // true (same reference)This is true for both loose and strict equality. If you need to compare the contents of two arrays or objects, you need a different approach.
What About NaN?
NaN is the only value in JavaScript that is not equal to itself:
console.log(NaN === NaN); // false
console.log(NaN == NaN); // falseUse Number.isNaN() to check for NaN. For more, see the NaN guide.
The Practical Rule
Use strict equality and strict inequality for every comparison. The only exception is value == null as a shorthand for value === null || value === undefined. This rule eliminates an entire category of bugs caused by unexpected type coercion. For an overview of all operators, see the operators guide.
Enable the eqeqeq rule in ESLint to enforce this automatically in your projects.
Rune AI
Key Insights
- === checks both value and type without converting anything.
- == converts types before comparing, which can produce unexpected results.
- Use === and !== as your default comparison operators.
- The only practical use for == is checking == null to catch both null and undefined.
- Objects and arrays are compared by reference with both == and ===.
- NaN === NaN is false. Use Number.isNaN() to check for NaN.
Frequently Asked Questions
Should I ever use == in JavaScript?
Why does JavaScript have both == and ===?
Is === faster than ==?
Conclusion
=== (strict equality) compares value and type without conversion. == (loose equality) converts types before comparing, which leads to surprising results like 0 == false being true. Always use === and !== as your default. The only reasonable exception is value == null, which cleanly checks for both null and undefined at once.
More in this topic
Is JavaScript Frontend or Backend? Full Guide
JavaScript is both a frontend and backend language. Learn the difference between browser JavaScript and Node.js, what each is used for, and which one you should learn first.
Learn JavaScript Step by Step Tutorial with Real Examples
Follow a hands-on tutorial that teaches JavaScript by building a real interactive page. Write your first variables, functions, and event listeners with examples you can run.
JavaScript Tutorial: Complete Beginner's Guide to Programming in 2025
A structured learning path for absolute beginners. Learn what to study first, how to practice, and which JavaScript concepts matter most when you are starting from zero.