Type Coercion and Equality
Type Coercion and Equality in JavaScript
Implicit vs explicit casting, ToPrimitive abstract operations, and strict equality.
The Airport Currency Exchange Counter
Type coercion is the automatic or implicit conversion of values from one data type to another. Understanding ECMAScript ToPrimitive and coercion rules is critical to avoiding subtle production bugs.
Strict Equality (===) vs Loose Equality (==)
`===` compares value and type without coercion. `==` applies complex abstract equality comparison algorithms, coercing operands to common types.
The 8 Falsy Values in JavaScript
`false`, `0`, `-0`, `0n` (BigInt), `""` (empty string), `null`, `undefined`, and `NaN`. All other values—including empty arrays `[]` and empty objects `{}`—are truthy!
String vs Numeric Coercion
Binary `+` operator prefers string concatenation if either operand is a string. Mathematical operators (`-`, `*`, `/`, `%`) always coerce operands to numbers.
ToPrimitive Object Conversion
When an object is coerced, JavaScript invokes its `[Symbol.toPrimitive](hint)`, falling back to `.valueOf()` and `.toString()`.
Dissecting classic coercion puzzles and Object.is equality:
// 1. Plus vs Minus Coercion
console.log("10" + 5); // "105" (String concatenation)
console.log("10" - 5); // 5 (Numeric subtraction)
console.log(true + true); // 2 (true coerces to 1)
// 2. The Famous [] == ![] Puzzle
// Step 1: ![] coerces truthy array to false
// Step 2: [] == false
// Step 3: [] coerces to "" -> "" == 0 -> 0 == 0 -> true!
console.log([] == ![]); // true
// 3. Object.is for Edge Cases
console.log(NaN === NaN); // false!
console.log(Object.is(NaN, NaN)); // true
console.log(+0 === -0); // true
console.log(Object.is(+0, -0)); // false
105
5
2
true
false
true
true
false
Using == with Falsy Values
The Risk: `null == undefined` is `true`, but `null == 0` is `false`. `"" == 0` is `true`, but `"0" == false` is `true`.
The Fix: Strictly adhere to `===` and `!==`. Only use `value == null` as a shorthand to check both `null` and `undefined`.
- ✓ Always default to strict equality (`===`).
- ✓ The only 8 falsy values: `false`, `0`, `-0`, `0n`, `""`, `null`, `undefined`, `NaN`.
- ✓ Empty arrays `[]` and empty objects `{}` are truthy in boolean contexts.
- ✓ `+` coerces to string if one operand is a string; `-`, `*`, `/` coerce to numbers.
- ✓ Use `Object.is(a, b)` for accurate `NaN` and `+0 / -0` comparisons.