Introduction
In this post, I want to share some JavaScript behaviors that often seem nonsensical at first, but actually reveal something about the language’s nature. Understanding them can help us avoid mistakes — and even take advantage of them.
The following examples are inspired by the book Eloquent JavaScript and by the quiz on JS is Weird web's site.
Another interesting resource, not taken into account for these examples, is jsdata.wtf that shows unexpected, or not so much, behaviors of the Date object.
So:
true + false === 1
Boolean values are converted into their numeric counterparts:
Number(true); // -> 1
Number(false); // -> 0
1 + 0; // -> 1
!!"" === false
The double exclamation mark (double NOT) converts any value to its corresponding boolean, based on its truthiness or falsiness, just like the Boolean() function :
!!""; // -> false ("" is falsy)
Boolean(""); // -> false
!!0; // -> false
!!"hello"; // -> true
!!666; // -> true
+true === 1
This is an example of type coercion, its minds JS tries to convert a value to a number. Internally JS use the Number() function:
Number(true); // -> 1
true == "true" // false
Here the loose equality operator (==) tries to convert the values to number:
Number(true); // -> 1
Number("true"); // -> NaN
1 == NaN; // -> false
null + 0 === 0
When performing arithmetic, null is coerced to 0:
Number(null); // -> 0
0 + 0; // -> 0
if ([] == false) → true but if ([]) → true
This one shows how truthiness and type coercion are two different mechanisms:
-
if([])When you use a value inside anifstatement, JavaScript simply checks its truthiness — no type conversion, no comparison.
if ([]) console.log("truthy"); // → truthy
Arrays (and any non-null objects) are truthy, even if they’re empty:
!![]; // -> true
Boolean([]); // → true
if ([] == false)
Now we’re using the loose equality operator ==, which triggers type coercion and the rules changes.
When comparing an object [] and a boolean false, JavaScript first converts the boolean to a number:
Number(false); // -> 0
// So we get
[] == 0;
Then it tries to convert the array to a primitive value (a number or string).
For an empty array:
[].toString(); // → ""
Number(""); // → 0
Finally we have:
0 == 0; // -> true
JS uses truthiness for if(x) and type coercion for x == y, that’s why something can be truthy and loosely equal to false at the same time.
We have the === operator to avoid these surprises...
0.1 + 0.2 !== 0.3
This behavior comes from how floating point numbers are represented based on the IEEE-754 standard used by JS and every major language.
The result is actually 0.30000000000000004, if you want to know more check the https://0.30000000000000004.com/ web site.
NaN !== NaN
A Not a Number value is, by definition, not equal to anything... not even to itself
'5' - 3 === 2 but '5' + 2 === '53'
The - operator always expects numbers, so '5' becomes 5.
But the + operator can mean addition or string concatenation, so if one operand is a string, the string concatenation wins.
'' == 0 -> true
The empty string is falsy and JS convert it to 0:
Number(''); // → 0
0 == 0; // → true
0/0 -> NaN
In divisions by 0, JavaScript does not always behave the same way:
1 / 0 // Infinity
-1 / 0 // -Infinity
0 / 0 // NaN
This behavior is caused too by the IEEE-754 standard that JS uses for its numbers.
[1,2,3] + [4,5,6] // -> "1,2,34,5,6"
Ones again the + operator treats values like strings if they are not numbers, so it performs a string concatenation with the two arrays.
If you want to save the , you have to put it before the 4:
[1,2,3] + [,4,5,6] // -> "1,2,3,4,5,6"
But not after the 3 because of the trailing coma will be ignored.
Conclution
This list could go on with more and more examples, but as you start to understand the why, the examples start to sound repetitive.
Most of these behaviors, which seem “weird” at first, are actually the result of how the language uses different strategies to handle the values it receives.
We can recognize in these examples some of JavasCript's main strategies, like type coercion and truthiness.
It’s thanks to those decisions JavaScript makes for us that we get certain freedoms — to be care, and to be creative too, like:
('b' + 'a' + + 'a' + 'a').toLowerCase(); // -> "banana"
😁 Thanks for reading!
Top comments (0)