Most of us working regularly with JavaScript are already more or less accustomed to some of the unexpected, quirky behavior it exhibits.
Take this classic example:
3 + "3" // "33"
Here’s one I stumbled across that really made me pause:
{} + [] // 0
Take a wild guess why this happens.
It’s because {} is not treated as an object literal here — instead, it’s interpreted as an empty code block. That leaves us with:
+[] // => 0
The unary + coerces the empty array into a number, and the result is 0.
🧩 More Examples of Type Coercion
The Stack Overflow answer I found also mentions:
[] + {} // "[object Object]"
Here, [] is treated as an empty string, and {} is treated as an object literal. JavaScript tries to concatenate them as strings — hence: "[object Object]".
How about:
[] + [] // ""
Straightforward, right? Both arrays are treated as empty strings. Concatenating two empty strings gives… an empty string.
And then there's this one:
{} + {} // NaN
This one’s a little trickier. The first {} is still treated as a code block. The second {} is coerced using the + operator. Since objects can’t be coerced into numbers, the result is NaN.
⚙️ Why It Matters in Real Code
I know, nobody is adding arrays and objects. This stuff is mostly a part of JS trivia.
But I actually stumbled into something similar that led me down the "type and coercion" rabbit hole.
const pl = // some complex formula with no type safety
if (pl) {
// update UI
}
The bug? Sometimes pl was 0, and the block didn’t execute — because 0 is falsy in JavaScript.
At first, the condition seemed intended to guard against undefined or null. So we tried a safer check:
if (typeof pl === "number") {
// update UI
}
Pretty solid — except for one catch:
typeof NaN // "number"
Yep. NaN is of type "number".
So this condition passed even when pl was NaN, and the UI still updated with invalid values.
We ended up adding a combination of checks (like !isNaN(pl)) and some stronger type safety upstream.
📌 Takeaways
It’s good to experiment with “obvious cases that would never happen in real life” to see how a programming language actually handles them. And also because it's fun.
Here are a few more I found interesting:
isNaN(null) // false; null is coerced to 0
isNaN([]) // false; [] coerced to 0
isNaN("") // false; "" coerced to 0
isNaN(true) // false; coerced to 1
isNaN(false) // false; coerced to 0
isNaN("text") // true
isNaN({}) // true; object can't be coerced to a number
isNaN(undefined) // true; undefined, not be coerced to a number; NaN
Got a favorite weird JavaScript case? Share it in the comments. Always open to learning something new.
Top comments (1)
sdf