JavaScript Type Coercion: A Deep Dive into the Weirdness
JavaScript's type coercion rules are basically a minefield for anyone who hasn't memorized the ECMAScript spec. If you're prepping for a React or Node.js interview, you'll likely hit these "predict the output" questions because they separate people who just "use" JS from those who actually understand the engine.
The core mental model for the + operator is simple: it tries to convert both sides to primitives. If either side ends up as a string, it defaults to string concatenation. If not, it attempts numeric addition.
Here is a practical tutorial on the most common traps.
The Coercion Cheat Sheet
Before diving into the snippets, keep these conversions in mind:
[](empty array): Stringifies to"", converts to number0.{}(empty object): Stringifies to"[object Object]", converts to numberNaN.null: Stringifies to"null", converts to number0.undefined: Stringifies to"undefined", converts to numberNaN.
Common Interview Snippets
1. Array Concatenation
console.log([] + []);
Output: "" (empty string)
Why: Both arrays are converted to primitives via .toString(). Since String([]) is "", you get "" + "", which is an empty string.
2. Array vs Object
console.log([] + {});
Output: "[object Object]"
Why: String([]) is "" and String({}) is "[object Object]". Because one operand is a string, JS performs concatenation: "" + "[object Object]".
3. The Parentheses Trap
console.log({} + []);
console.log(({} + []));
Output: "[object Object]" for both.
Why: Inside console.log or parentheses, {} is explicitly treated as an object literal. Both sides stringify and concatenate.
4. The eval / Bare Block Trap
eval('{} + []');
eval('({} + [])');
Output: 0 then "[object Object]"
Why: In the first case, the engine sees {} as an empty code block, not an object. It ignores the block and evaluates + []. The unary + operator converts [] to a number, which is 0.
Equality Gotchas
One of the most frequent "gotchas" is how JS handles NaN and null.
NaN === NaN: This isfalse.NaNis the only value in JS not equal to itself. To check for it, useNumber.isNaN()orObject.is().typeof null: Returns"object". This is a legacy bug from the first version of JS that was never fixed to avoid breaking the web.[]and{}Truthiness: Even though they are "empty," both are truthy.
=== to avoid implicit coercion and Object.is() when you need to detect NaN.
Strict equality is a lifesaver. Have you found any edge cases where it still fails in JS?