You might be wondering why I am writing less these days. I assure you, it’s not because I am getting lazy (I am ATM 🤩), it’s just that I am on a long overdue holiday. But to keep my juices going, I thought now that I am having fun, let’s write a fun post 😊.
In this post I will go through some of the funniest yet unbelievable JavaScript snippets ever. Are you ready?
[]
is equal ![]
Array is equal to not array 😂:
;[] == ![] // -> true
💡 What’s happening?
The abstract equality operator converts both sides to numbers before comparing them, and both sides will be converted to 0
for different reasons. Arrays are truthy, so the right hand side becomes false which then is coerced to 0
. On the left however, the empty array is coerced to a number without becoming a boolean first, and empty arrays are coerced to 0
, despite being truthy 🤯.
true
is false
True is false:
!!'false' == !!'true' // -> true
!!'false' === !!'true' // -> true
💡 What’s happening?
true
is truthy
and is represented by value 1 (number), true
in string form, is NaN
. So:
true == 'true' // -> false
false == 'false' // -> false
false
is not the empty string, so it’s a truthy value, so:
!!'false' // -> true
!!'true' // -> true
Cool, ha? 😎
Let’s create a banana:
'b' + 'a' + +'a' + 'a' // -> baNaNa
💡 What’s happening?
This one is an old trick, remixed. The expression is converted to "ba" + (+"a") + "a"
, and since "a"
is converted to a number, it becomes NaN
.
You wouldn’t believe this in your wildest dreams, but:
;(![] + [])[+[]] +
(![] + [])[+!+[]] +
([![]] + [][[]])[+!+[] + [+[]]] +
(![] + [])[!+[] + !+[]]
// -> 'fail'
💡 What’s happening?
If we break this lot into smaller pieces, we notice that the following pattern occurs often:
![] + [] // -> 'false'
![] // -> false
We try adding []
to false
, but because of a number of function calls internally, we’ll end up converting the right operand into a string:
![] + [].toString() // -> 'false'
Thinking of a string as an array we can access its first character via [0]
:
'false'[0] // -> 'f'
The rest is obvious, but the i
is tricky. The i
in fail is grabbed by generating the string falseundefined
and taking the element on index ['10']
.
Array equality is evil in JavaScript, see below:
[] == '' // -> true
[] == 0 // -> true
[''] == '' // -> true
[0] == 0 // -> true
[0] == '' // -> false
[''] == 0 // -> true
[null] == '' // true
[null] == 0 // true
[undefined] == '' // true
[undefined] == 0 // true
[[]] == 0 // true
[[]] == '' // true
[[[[[[]]]]]] == '' // true
[[[[[[]]]]]] == 0 // true
[[[[[[ null ]]]]]] == 0 // true
[[[[[[ null ]]]]]] == '' // true
[[[[[[ undefined ]]]]]] == 0 // true
[[[[[[ undefined ]]]]]] == '' // true
💡 What’s happening?
The explanation behind this is rather long. So I introduce you to section 7.2.13 Abstract Equality Comparison of the specification.
parseInt
is just badparseInt
is famous by its quirks, I just mention one of the most famous ones:
parseInt('f**k') // -> NaN
parseInt('f**k', 16) // -> 15
💡 What’s happening?
This happens because parseInt
will continue parsing character by character until it hits one it doesn’t know. The f
in f**k
is the hexadecimal digit 15
.
NaN
is Type of NaN
is a number
:
typeof NaN // -> 'number'
💡 What’s happening?
Explanations of how typeof
and instanceof
operators work:
This one is gold:
1 < 2 < 3 // -> true
3 > 2 > 1 // -> false
💡 What’s happening?
Why does this work that way? Well, the problem is in the first part of an expression. Here’s how it works:
1 < 2 < 3 // 1 < 2 -> true
true < 3 // true -> 1
1 < 3 // -> true
3 > 2 > 1 // 3 > 2 -> true
true > 1 // true -> 1
1 > 1 // -> false
You can fix this with greater than or equal operator (>=
):
3 > 2 >= 1 // true
Read more about Relational operators in the specification:
And that’s just some of the fun we can have with JavaScript. No wonder some people do not like it, since they don’t understand how it works 😂.