JavaScript is a powerful and flexible language, but it has some quirks that can catch even experienced developers off guard. Here are 10 of the most surprising JavaScript behaviors—and why they happen.
1. 0.1 + 0.2 !== 0.3 (Floating-Point Precision)
console.log(0.1 + 0.2 === 0.3); // false console.log(0.1 + 0.2); // 0.30000000000000004
JavaScript uses IEEE 754 floating-point arithmetic, which can’t precisely represent some decimal fractions. This leads to tiny rounding errors.
console.log([] + {}); // "[object Object]" console.log({} + []); // 0 (in some environments)
[] + {} converts both to strings ("" + "[object Object]").
{} + [] is interpreted as an empty block {} followed by +[], which coerces [] to 0.
3. NaN === NaN is false
console.log(NaN === NaN); // false
NaN (Not-a-Number) is defined as unequal to itself in the IEEE 754 standard. Use isNaN() or Number.isNaN() to check for NaN.
4. "5" + 3 vs "5" - 3 (String vs Number Coercion)
console.log("5" + 3); // "53" (string concatenation) console.log("5" - 3); // 2 (numeric subtraction)
The + operator favors string concatenation if one operand is a string, while - forces numeric conversion.
5. true == "1" (Loose Equality Quirks)
console.log(true == 1); // true console.log(true == "1"); // true console.log(true == "2"); // false
Loose equality (==) performs type coercion. true becomes 1, and "1" becomes 1, so they’re equal.
6. Math.max() < Math.min()
console.log(Math.max()); // -Infinity console.log(Math.min()); // Infinity
With no arguments, Math.max() starts at -Infinity (seeking the largest number), while Math.min() starts at Infinity.
7. "b" > "a" > 1 is false
console.log("b" > "a" > 1); // false
This evaluates as:
- "b" > "a" → true (lexicographical order)
- true > 1 → false (true converts to 1, so 1 > 1 is false)
8. Array(3).map(() => "x") Doesn’t Fill the Array
console.log(Array(3).map(() => "x")); // [empty × 3]
Array(3) creates a sparse array with no actual elements, so map() skips them. Use Array(3).fill().map(...) instead.
9. typeof null is "object"
console.log(typeof null); // "object"
A bug in early JavaScript that was never fixed for backward compatibility. Use === null to check for null.
10. "🤦".length === 2 (Unicode Surprise)
console.log("🤦".length); // 2
JavaScript uses UTF-16, and some emojis (like "🤦") are represented as surrogate pairs, taking up two code units.
Conclusion
JavaScript’s flexibility leads to some unexpected behaviors due to type coercion, floating-point math, and historical quirks. Understanding these can help you debug tricky issues and write more robust code.
Top comments (0)