DEV Community

Cover image for Think You Know JavaScript? These 15 Quirks Will Change Your Mind! ๐Ÿ’ฅ
Jagroop Singh
Jagroop Singh

Posted on

Think You Know JavaScript? These 15 Quirks Will Change Your Mind! ๐Ÿ’ฅ

JavaScript is a flexible, quirky language that can sometimes leave you scratching your head. If you've spent any amount of time working with JS, you've probably encountered a few unexpected behaviors, like 0 == "0", or wondered why 0.1 + 0.2 !== 0.3.

In this blog, we'll dive into some of JavaScript's most puzzling features, helping you understand how the language works under the hood and avoid potential pitfalls in your code. Ready? Letโ€™s get started! ๐Ÿš€


1. "False" == 0 but Not "False" == "0" ๐Ÿคฏ

You might expect "False" to be equal to "0", but here's the catch: "False" == 0 is true, but "False" == "0" is false.

This happens because JavaScriptโ€™s equality operator (==) triggers type coercion. When you compare a string to a number, JS tries to convert the string to a number first. And since "False" doesn't really have a numeric value, it becomes NaN. But "0" becomes the number 0, so when we compare 0 == 0, itโ€™s true!

Example:

console.log("False" == 0);   // true (coerces "False" to NaN, NaN == 0 is false but coerces NaN to 0)
console.log("False" == "0"); // false
Enter fullscreen mode Exit fullscreen mode

2. 0.1 + 0.2 Isn't Exactly Equal to 0.3 ๐Ÿ˜ฒ

This one is a classic!

console.log(0.1 + 0.2 === 0.3); // false
Enter fullscreen mode Exit fullscreen mode

Why? JavaScript uses IEEE-754 for floating-point arithmetic, which can cause precision issues. So, 0.1 + 0.2 doesnโ€™t exactly add up to 0.3. Itโ€™s a common pitfall in financial apps, for example.

Solution:

For comparisons like this, use a small tolerance:

const isEqual = Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON;
console.log(isEqual); // true
Enter fullscreen mode Exit fullscreen mode

3. typeof null Returns "Object" ๐Ÿง

This oneโ€™s a head-scratcher. When you check the type of null, it gives you "object".

console.log(typeof null); // object
Enter fullscreen mode Exit fullscreen mode

Why? Well, it's a historical mistake in JavaScript's early days. The type of null should have been "null", but due to a bug, it ended up being "object". But now, itโ€™s too late to change it without breaking old code.


4. [1,2,3] + [4,5,6] = "1,2,34,5,6" ๐Ÿ˜…

Here's another weird one! When you add two arrays together, JavaScript converts them to strings before adding them. The result? A strange concatenation!

console.log([1, 2, 3] + [4, 5, 6]); // "1,2,34,5,6"
Enter fullscreen mode Exit fullscreen mode

This happens because arrays get converted to strings, resulting in "1,2,3" and "4,5,6", and when those are added together, it becomes "1,2,34,5,6".


5. NaN === NaN is False ๐Ÿ”„

Yes, NaN (Not-a-Number) is a special value in JavaScript, and itโ€™s never equal to itself.

console.log(NaN === NaN); // false
Enter fullscreen mode Exit fullscreen mode

Why? The logic behind this is that NaN is not a real number, and thus it cannot be equal to anything, even itself.

Tip:

To check for NaN, use Number.isNaN():

console.log(Number.isNaN(NaN)); // true
Enter fullscreen mode Exit fullscreen mode

6. Why [] == ![] is True But [] == [] is False ๐Ÿ˜ฑ

In JavaScript, [] == ![] is true, but [] == [] is false. How?

  • [] == [] is false because two different empty arrays are not the same object reference.
  • [] == ![] works because ![] coerces to false, and an empty array is a truthy value. Thus, [] == false becomes true after coercion.

7. Math.max() Returns -Infinity ๐Ÿค”

When you call Math.max() without any arguments, it returns -Infinity.

console.log(Math.max()); // -Infinity
Enter fullscreen mode Exit fullscreen mode

This happens because JavaScript considers the absence of arguments as a comparison with negative infinity. If you need a fallback value, use:

const max = Math.max(...numbers) || 0;
Enter fullscreen mode Exit fullscreen mode

8. 0 == "0" and 0 == [] but "0" != [] ๐Ÿ”€

JavaScript's == operator does some bizarre things with type coercion. For example, 0 == [] is true, but "0" == [] is false.

console.log(0 == "0"); // true
console.log(0 == []);  // true
console.log("0" == []); // false
Enter fullscreen mode Exit fullscreen mode

This happens because [] is first coerced to an empty string when compared with "0", making the second comparison false.


9. undefined + 1 Returns NaN, but null + 1 Returns 1 ๐Ÿคท

Hereโ€™s a peculiar one. When you add undefined to a number, you get NaN. But adding null to a number results in 1.

console.log(undefined + 1); // NaN
console.log(null + 1);      // 1
Enter fullscreen mode Exit fullscreen mode

Why? undefined is not a number, so it gives you NaN, while null is treated as 0 in arithmetic operations.


10. New Array(3) vs [,,] ๐Ÿ˜ณ

Whatโ€™s the difference between new Array(3) and [,,]?

  • new Array(3) creates an empty array with 3 slots (no values), whereas [,,] creates an array with 2 undefined values.
console.log(new Array(3)); // [ <3 empty items> ]
console.log([,,]);          // [undefined, undefined]
Enter fullscreen mode Exit fullscreen mode

11. parseFloat("3.14abc") Works, But parseInt("3.14abc") Doesnโ€™t ๐Ÿ˜…

When parsing strings with numbers and text, parseFloat will try to read the number up to the first non-numeric character. parseInt, on the other hand, stops at the first non-numeric character and doesnโ€™t work for decimal numbers.

console.log(parseFloat("3.14abc"));  // 3.14
console.log(parseInt("3.14abc"));    // 3
Enter fullscreen mode Exit fullscreen mode

12. [] + {} vs {} + [] ๐Ÿ”„

Did you know the order of operations matters in JavaScript? [] + {} results in a string, but {} + [] does nothing.

console.log([] + {});   // "[object Object]"
console.log({} + []);   // "[object Object]"
Enter fullscreen mode Exit fullscreen mode

13. 0.1 * 0.1 Prints โ€œ0.010000000000000002โ€ ๐Ÿ“

JavaScriptโ€™s floating-point arithmetic can sometimes give unexpected results, like in the case of 0.1 * 0.1:

console.log(0.1 * 0.1); // 0.010000000000000002
Enter fullscreen mode Exit fullscreen mode

This occurs due to binary floating-point precision errors.


14. Truthy and Falsy Values ๐Ÿšฆ

In JavaScript, certain values are treated as falsy: "", 0, null, undefined, NaN, and false. Anything else is truthy.

console.log(!!"");      // false
console.log(!!0);       // false
console.log(!!null);    // false
console.log(!!1);       // true
Enter fullscreen mode Exit fullscreen mode

Conclusion: JavaScript is full of surprises! ๐ŸŽ‰

Now that we've covered some of JavaScript's most curious quirks, it's time for you to test your understanding. Ready for some tricky questions? ๐Ÿค”

  1. Why does typeof NaN return "number" when NaN is not a number?
  2. What do you get when you subtract Infinity - Infinity in JavaScript?

Drop your answers below! Letโ€™s see how many of you get them right! ๐Ÿ˜Ž

Top comments (25)

Collapse
 
moopet profile image
Ben Sinclair

99.1% of these issues people have with JavaScript are caused by trying to compare or manipulate things of different types.

74.8% of these things are common to other programming languages.

I feel like most of the things people find weird about JS are because they're trying to do something that if you stop and think about it for more than a second, well, it doesn't make sense.

Collapse
 
lisaresnick10001 profile image
Lisa Resnick

This is pretty accurate, but one of the main reasons JavaScript is so popular is its "flexible and forgiving nature." People often mix and match different types because the language allows it. For

example:

console.log(1 + "1"); // "11"
console.log(1 - "1"); // 0

This kind of behavior can confuse new developers. But if you approach JavaScript from the perspective of strongly typed languages (like Java or C#), it might seem "weird."

The truth is, if developers understand type conversions and implicit coercion, JavaScript doesn't feel so strange anymore. And as you said, "if you stop and think about it," most of the problems do go away โ€” that's the golden rule of programming in any language. ๐Ÿ˜„

Collapse
 
jagroop2001 profile image
Jagroop Singh

@moopet ,
I agree !!
Itโ€™s true that many JavaScript quirks stem from type coercion and comparison issues, which can often be avoided and not widely used.

Collapse
 
freshcaffeine profile image
Andy Robinson

Heres a fun one that trips up lots of people...

 const christmasDay = new Date(2024, 12, 25);

 const christmasDayString = christmasDay.toLocaleDateString("en-GB", {
   weekday: "long",
   year: "numeric",
   month: "long",
   day: "numeric"
 });
// result: Saturday 25 January 2025
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jagroop2001 profile image
Jagroop Singh

Yes @freshcaffeine ,
Date object are zero-indexed. This means 0 is January, 1 is February, and so on.That's why it cause issue.

Collapse
 
freshcaffeine profile image
Andy Robinson • Edited

yes, but only month is zero-indexed. But not day and year.. which increased confusion more - I've seen some interesting bugs because of this.

Collapse
 
hbthepencil profile image
HB_the_Pencil
  1. I'm gonna guess... typeof NaN returns "number" because it is a placeholder for something that should be a number.
  2. It ought to be 0, but I'm guessing it's actually Infinity because subtracting anything from Infinity is Infinity. (Either that or -Infinity because it subtracts until it cannot subtract any more.)

This is a fun article! I'd love to see more of these!

Collapse
 
jagroop2001 profile image
Jagroop Singh

@hbthepencil , thanks for trying , but the actual answers are:

  1. NaN is technically a special value of the Number in javascript.
  2. When you subtract Infinity from Infinity in JavaScript, you get NaN. This is because the operation is undefinedโ€”subtracting two infinite quantities does not yield a finite number or a meaningful result.
Collapse
 
hbthepencil profile image
HB_the_Pencil

Ah, I was almost there on the first one... Thanks!

Collapse
 
rjbaddeley profile image
Robert Baddeley

The 0.1 + 0.2 and the 0.1*0.1 is not really JavaScript but because floating point math is not precise when it comes down to storing the bits in memory. Many other languages have the same issue. Less a quark of JavaScript and more of a quark of computer science.

Collapse
 
jagroop2001 profile image
Jagroop Singh

Yes , I agree @rjbaddeley

Collapse
 
tomasdevs profile image
Tomas Stveracek

Great article! For those interested, I've also written a similar piece diving into JavaScript quirks: JavaScript Quirks: What You Need to Know. Feel free to check it out! ๐Ÿ˜Š

Collapse
 
jagroop2001 profile image
Jagroop Singh

Great post @tomasdevs !!

Collapse
 
john12 profile image
john

Finally , the old programming language still have bugs, console.log(typeof null); // object which shows no one is perfect even javascript

Collapse
 
jagroop2001 profile image
Jagroop Singh

Image description

Collapse
 
jagroop2001 profile image
Jagroop Singh

Haha, yes, even JavaScript has its quirks!

Collapse
 
paxnw profile image
caga

[1,2,3] + [4,5,6] = "1,2,34,5,6" is asked in my recent interview and I fails to answer it correctly, and after checking the solution I just byheart this and will never forget that.

Collapse
 
jagroop2001 profile image
Jagroop Singh

Yes that's tricky one !!

Collapse
 
ezekiel_77 profile image
Ezekiel

And thats why we use typescript

Collapse
 
jagroop2001 profile image
Jagroop Singh

Exactly @ezekiel_77 , these quirks shows it's important to use typescript in js based projects.

Collapse
 
works profile image
Web

Nice javascript tricky points.

Collapse
 
jagroop2001 profile image
Jagroop Singh

Thanks @works

Collapse
 
lexlohr profile image
Alex Lohr

About #5, you can also use Object.is(NaN, NaN). About #11, parseInt does exactly what is should and returns the integer value of the number. The rest is IEEE754 and type coercion wackyness - and after a few decades of writing JS, those were no longer surprising.

About your tricky questions: NaN is of type number, because it is specified like this in IEEE754 (not only in JS) and Infinity - Infinity yields NaN.