Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding some Javascript code [duplicate]

Tags:

javascript

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?

like image 963
ieatpizza Avatar asked May 30 '15 19:05

ieatpizza


2 Answers

!! 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;
like image 95
Spencer Wieczorek Avatar answered Nov 04 '22 22:11

Spencer Wieczorek


There are three major things to undertand in this particular example:

  1. What is the nature and behavior of the unary + operator
  2. What is the nature and behavior of the logical NOT operator
  3. How the aforementioned operators interact with empty arrays

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.

like image 35
Sampson Avatar answered Nov 04 '22 22:11

Sampson