I came across this Javascript snippet:
var sum = +((!+[] + !![] + !![] + []) + (!+[] + !![] + !![] + !![] + !![] + !![]));
This example evaluates to 36.
What is happening here and what's the best way to understand/read it?
!!
is a way to convert to a Boolean being either true
or false
. A numerical representation for true
is 1
and for false it's 0
. So for example:
!![] => true => 1
When you convert +[]
to a number it goes to 0
(when converted to a Boolean it's false), so !+[]
is true
. Now lets convert those items:
var sum = +((!+[] + !![] + !![] + []) + (!+[] + !![] + !![] + !![] + !![] + !![]));
var sum = +((true + true + true + []) + (true + true + true + true + true + true));
var sum = +((3 + []) + (6));
Now note (3 + []) => "3"
, evals to a string. Then the string is concatenated with the number 6
:
var sum = +("3" + 6); // "36"
Then finally the +("36")
turns the string into a number:
var sum = 36;
There are three major things to undertand in this particular example:
The unary + operator converts its operand (the value to its right) to a number. The logical NOT operator either converts its operand to a boolean, or flips the value if the operand is already a boolean.
Both of these operators initially get the value of the operand before doing anything. So when the operand is an array, we need to understand what the value of the array is.
Lets try a few things first to explore how these operators behave with an array:
+[]; // 0
![]; // false
The +
operator gets the value of its operand, and then converts that to a number. The !
operator gets the value of its operand, and then converts that to a boolean.
What if we were to use the !
operator twice, and use the +
operator on that resulting value?
!![]; // true
+!![]; // 1
Now we're seeing the ability to create both the number 0, and the number 1. Given this power, we can begin to do some arithmetic (note that I am using the grouping operator for legibility:
(+!![]) + (+!![])
This results in 1 + 1
, equaling 2. Performing operations like these enough to achieve 36
would require quite a bit of clutter, but the example above leverages the Addition Operator as a short cut.
The addition operator performs string concatenation, as well as numerical addition. So "foo"+"bar"
returns "foobar". Likewise, numbers in string-form will be concatenated, rather than added: "3"+"6"
returns "36". The code provided in the question achieves number to string conversion by leveraging the inherent behavior of arrays:
["Hello"].toString(); // "Hello"
[].toString(); // ""
With the addition operator, if any side of the operand is a string, the result will also be a string (see step 7 of 11.6.1). Because the array's .toString
method is called, the array produces an empty string. When this string is added to a type of number, a string of that number results:
7 + ""; // "7"
This can be leveraged to concatenate, rather than add, two numbers. In the following example, I adopted our previous code that resulted in 2
, and added a couple more grouping operators for legibility:
( ( +!![] ) + [] ) + ( ( +!![] ) + [] ) // "11"
On the left-hand side of the middle +
operator we generate the number one, and add it to the string produced by an empty array. We then do the same thing to the value on the right-hand side of the middle +
operator. The result, two strings with the value "1"
. The middle operator then concatenates these two strings, yielding "11"
.
Given this knowledge, you should be able to revisit the code in your question, and quickly make sense of the individual portions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With