The Simple Rule
Always use === (strict equality) unless you have a specific reason to use ==.
== (Loose Equality)
The loose equality operator performs type coercion before comparing:
1 == '1' // true (string converted to number)
0 == false // true (false converted to 0)
null == undefined // true (special case)
'' == 0 // true (empty string converted to 0)
=== (Strict Equality)
The strict equality operator compares both value and type:
1 === '1' // false (different types)
0 === false // false (different types)
null === undefined // false (different types)
'' === 0 // false (different types)
Why === is Better
1. Predictable Behavior
// With ==, these are all true (confusing!)
0 == '' // true
0 == '0' // true
'' == '0' // false (wait, what?)
// With ===, it's clear
0 === '' // false
0 === '0' // false
'' === '0' // false
2. Avoids Bugs
function isValid(value) {
// Bug: 0 and '' would pass with ==
if (value == null) return false;
return true;
}
isValid(0); // true (maybe not intended)
isValid(''); // true (maybe not intended)
// Better:
function isValidStrict(value) {
if (value === null || value === undefined) return false;
return true;
}
When to Use ==
There's one legitimate use case for ==:
// Checking for null OR undefined
if (value == null) {
// value is null or undefined
}
// Same as:
if (value === null || value === undefined) {
// ...
}
But with modern JavaScript, you can use nullish coalescing instead:
const result = value ?? 'default';
Type Coercion Table
| x | y | x == y | x === y |
|---|---|---|---|
| 1 | '1' | true | false |
| null | undefined | true | false |
| 0 | false | true | false |
| [] | false | true | false |
| '' | false | true | false |
Best Practice
Configure your linter to enforce === (eqeqeq rule in ESLint).
{
"rules": {
"eqeqeq": "error"
}
}
Summary
- === compares value AND type (strict)
- == compares value after type coercion (loose)
- Always use === unless you specifically need type coercion
- Most == usage is unintentional and causes bugs