5 Strange Things About JavaScript Explained (+ a bonus)

NicolasBrondinBernard

Author
@NicolasBrondinBernard

You've surely seen these examples circulating online, today I'll explain to you the why and how behind it.

Article published on 14/12/2020, last updated on 10/08/2026

I am a JavaScript developer, and sometimes I find myself crossing my fingers when running a script for the first time, hoping everything goes as planned, and my wife often asks me:

But why wouldn't it work? It's a computer, it only does what you tell it to do!

And in a way, she's more than right, but at the same time there are situations where even if our logic is sound, something goes wrong because of the singular nature of this language that is JavaScript.

So I'm going to present you with 5 examples of unexpected results in order to explain the underlying reason behind each one!

JavaScript, I love you, I love you not.

The following examples almost all stem from the fact that JavaScript is a dynamically typed language, which means that when we assign a value to a variable, it will dynamically guess the type based on the variable.

During an operation, JavaScript will try to transform the content of the original variable to make it fit the type expected by the operation, which can lead to sometimes strange results.

The true nature of NaN

console.log(typeof NaN)
// => "number"

console.log(NaN == NaN);
// => false

What? The value NaN, which means "Not a Number," is actually a number?

Yes indeed.

You might think that NaN is a specific value like null or undefined, but no, NaN really is a number, and worse, it's not even equal to itself, as you can see in the example above.

The reason is simple: NaN serves as a result in several cases, for example:

  • when trying to convert data that does not represent a number (for example the string "blue")
  • during a mathematical expression that is impossible for the computer system to calculate but whose result is indeed a number, such as the square root of a negative number.
  • ...

It is therefore impossible to know whether two NaN values have the same meaning, which is why NaN == NaN always returns false!

This is why you should always use the isNaN() method

Decimal numbers don't exist

console.log(0.1+0.2)
// => 0.30000000000000004

console.log(0.1+0.2==0.3);
// => false

When we think of operations whose results are known to everyone, we think of additions in mathematics, and yet as you can see, we can't always rely on them.

So does JavaScript not even know how to count properly?

You might be tempted to believe that this erroneous result is due to the language itself, and yet its origin lies at a much lower level, to the point that the same problem exists in most other languages.

The reason is quite complex, but to put it simply, it stems from the fact that our electronic circuits are designed to store integers (in binary form), and that in order to represent decimal numbers, these must resort to fractions.

The very nature of fractions in mathematics means that some of them resolve into an infinite sequence of digits (1/3 = 0.33333333...4 in base 10), and when we switch to base 2 (binary system), certain fractions that are simple in base 10 become complex in base 2. This is the case for 1/10 and 2/10, the problematic numbers in the previous operations.

If you want more precise and mathematically accurate explanations, I recommend reading this article on Medium.

To avoid any problems with calculations requiring flawless precision, such as in financial systems, you will need to use integers as the basis for your calculations, for example by counting in cents.

Chameleon operations

console.log(9+"1")
// => "91"

console.log(9-"1");
// => 8

The difference between the + and - operators in JavaScript is that one represents an arithmetic operation (-) while the other represents both an operation and a software function.

The "+" operator gives us the ability to both add numbers and concatenate two strings. Priority is given to concatenation, so if either of the two values (on the left or right) of the operator is a string, JavaScript will convert the other value into a string and join them together.

The "-" operator is different because it only represents the mathematical operation, so it will try to convert the values on either side into numbers before performing the operation, and the result will therefore be a number (possibly NaN if the conversion goes wrong).

Falsy and truthy values

console.log(true+true+true)
// => 3

console.log(true == 1);
// => true

console.log("" == false);
// => true

In JavaScript there are primitive true and false values, but there is also the concept of truthy and falsy values, allowing for more flexible calculations, but also often leading to confusion.

During a condition (with the ==, ===, <, > and other operators) the result will be a primitive boolean value, but it can be calculated from values that are considered "roughly" true or false. For example, the values:

  • "" (empty string), "false", 0 (zero), or "0" are considered falsy
  • "1" or 1 are considered truthy

Be careful, no other string is considered truthy, not even the string "true".

To avoid any problems, favor the === operator, which will not take truthy and falsy values into account, but only true and false.

Empty arrays

console.log([]+[])
// => ""

console.log([] == 0);
// => true

When we add two empty arrays together, JavaScript returns an empty string, because as we saw earlier, the "+" operator tries to convert its operands into strings if they are not already of type "number".

And surprise, we discover that an empty array actually corresponds to an empty string, because indeed in every programming language, a string is actually a disguised array of characters. You can even try the following test:

console.log([1,2,3]+"");
// => "1,2,3"

When it needs to convert an array into a string, JavaScript simply separates each value with a comma, so for an empty array we get a simple empty string.

Let's add empty strings together, and we'll get an empty string back, and let's compare an empty string (falsy) with the number 0 (falsy), and the result will be "true."

As a bonus

console.log(Math.min())
// => Infinity

console.log(Math.max());
// => -Infinity

Instinctively, one might imagine that the mathematical method min() called without a parameter would return the value -Infinity, and the opposite for the max() method.

The reason lies in the technical implementation: since Math.min(3) must return 3, and Math.min(3, 4) must also return 3, there needs to be an absolute comparison value. If this value were initialized to "Infinity", the first example would be equivalent to calling Math.min(Infinity, 3) and the result would therefore be incorrect.


Finished reading this article?
Our complete courses
Take it to the next level with our courses!

Complete courses, exercises and certificates to really learn programming!

4.8 average rating

Comments (0)

to leave a comment

No comments yet