Equality & Coercion — == vs === and Why It Matters
BeginnerJavaScript will convert types to make a comparison succeed. == does this conversion, === does not, and knowing the handful of rules turns "weird" behaviour into predictable behaviour.
Overview
Coercion is the feature people cite when they call JavaScript a bad language, and it is genuinely the source of real bugs. But the rules are short. The loose equality operator == converts operands to a common type before comparing; strict equality === compares type and value with no conversion. The practical advice is simple — use === always, with exactly one useful exception — but you still need to read the rules, because you will encounter == in other people's code and in every interview.
The Rules Worth Memorising
Loose equality has a specific algorithm. These are the cases that actually appear in real code and interviews.
// Strict: no conversion, compares type then value
1 === '1' // false
null === undefined // false
// Loose: converts first
1 == '1' // true — string becomes number
0 == false // true — boolean becomes number
'' == false // true — both become 0
null == undefined // true — special-cased in the spec
null == 0 // false — null only equals undefined
// The one genuinely useful ==
if (value == null) {
// true for BOTH null and undefined, nothing else
}
// same as: value === null || value === undefinedTruthiness
Every value is either truthy or falsy in a boolean context. There are exactly eight falsy values; memorise those and everything else is truthy — including empty arrays and empty objects, which surprises people coming from Python.
// The complete falsy list:
false, 0, -0, 0n, '', null, undefined, NaN
// Everything else is truthy, including:
if ([]) {} // runs — empty array is truthy
if ({}) {} // runs — empty object is truthy
if ('0') {} // runs — non-empty string
// The classic bug:
function setCount(n) {
if (!n) return // 0 is falsy — this rejects a valid 0
...
}
// Fix: be explicit about what you are rejecting
if (n === undefined) return?? and ?. — The Modern Fixes
Nullish coalescing and optional chaining exist specifically to avoid the truthiness trap. ?? falls back only on null or undefined, where || falls back on any falsy value.
// || falls back on ANY falsy value — usually not what you want
const pageSize = input.size || 20 // 0 becomes 20. Bug.
// ?? falls back only on null/undefined
const pageSize = input.size ?? 20 // 0 stays 0. Correct.
// Optional chaining short-circuits instead of throwing
const city = user?.address?.city // undefined if either is missing
const first = list?.[0]
const result = callback?.() // only calls if callback exists
// Combined, the common shape when reading API responses:
const name = response?.data?.user?.name ?? 'Anonymous'Key Points to Remember
- 1=== compares type and value with no conversion; == converts first — default to === always
- 2value == null is the one useful loose comparison: true for null and undefined, nothing else
- 3Exactly eight falsy values: false, 0, -0, 0n, "", null, undefined, NaN — empty arrays and objects are truthy
- 4?? falls back only on null/undefined, || falls back on any falsy value — using || for defaults breaks on 0 and ""
- 5?. short-circuits to undefined instead of throwing, which is what makes reading nested API responses safe
Interview Questions
Sign in to ask AriaWhat is the difference between == and ===? When would you deliberately use ==?
List the falsy values in JavaScript. Is an empty array truthy or falsy?
Why does `const size = input.size || 20` have a bug, and how does ?? fix it?
Ask Aria about Equality & Coercion — == vs === and Why It Matters
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.