View RSS Feed

keyboard

Messing with Javascript

Rate this Entry
Hey all,
I've been fiddling with JavaScript and decided to share a neat little thing (its completely useless).

Finished Code
Code:
console.log(+[[-~[]<<~[]][+[]]+[]][+[]][++[[]][+[]]+[+[]]]); //Prints 8
Now for the break down -

Pre-note - I use this function while playing with variables. It outputs the value and type of a variable. (The counter is to force the developer console to display each seperately)
Code:
var counter = 0;
function pLog(arg) {
	console.log(++counter + ": " + typeof(arg) + "(" + arg + ")");
}


First thing you have to understand is that you can cast a string to a number be using a math operator on it.
E.g.
Code:
pLog("7");		//Outputs string(7)
pLog(+"7");		//Outputs number(7)
Notice the +"7".
This takes the string "7" and converts it to the number 7.
This trick works with several mathematical operators. But + doesn't modify the actual value while converting it.


The next thing to understand is you can convert some other types of variables, not just strings, to numbers in the same way.
E.g.
Code:
var x = false;
var y = [];
var z = {};
var q = function() {};

pLog(x);					//boolean(false)
pLog(+x);					//number(0)

pLog(y);					//object(0)
pLog(+y);					//number(0)

pLog(z);					//object([object Object])
pLog(+z);					//number(NaN)

pLog(q);					//function(function () {})
pLog(+q);					//number(NaN)

Ok, so we know that when we use math operators on an empty array it outputs 0.

Operators
There are two special operators in the original code: "~" and "<<". These are called Bitwise Operators.

The ~ operator is called the Bitwise NOT. It inverts the bits of a number.
Code:
var x = 10;
pLog(x);					//number(10)
pLog(~x);					//number(-11)
You may notice that this operator is the equivalent of the math function -(N + 1)


The << is the Left Shift operator. It shifts a number in binary representation N bits to the left, shifting in zeroes from the right.
If you don't understand any of this, I'd recommend researching binary numbers.
Code:
var x = 3;

pLog(x);					//number(3)
pLog(x<<3);					//number(24)
The decimal number 3 is represented as "11" in binary.
If you shift that to the left by 3 places, padding with zeroes that'd be binary "11000" which is 24!



Breaking down the actual code
First thing to do is make it a bit more readable -

Code:
+[[ -~[] << ~[] ][+[]] + []][ +[] ][ ++[[]][ +[] ] + [+[]] ]
Ok so we know that when we use math operators on an empty array it gives 0
We also know that ~ is basically -(N + 1)
so
+[] == 0
and
~[] == ~0
~0 == -1

So we know that +[] is zero and ~[] is negative one.
The minus before the ~[] simply changes it from a negative to a positive number (double negative).


Going through and replacing those through the code we get
Code:
+[[ 1 << -1 ][0] + []][0][ ++[[]][0] + [0] ]
Definitely looking a bit more readable.
Notice the ++[[]][0]

If we have an array -
Code:
var x = [10, 2];
We know that x[0] will return the first value of the array.

So [[]] is the array and [0] returns the first value of that array (which is [], an empty array)
Since +[] is 0 and ++ is the incremental operator, ++[] gives us 1.
Code:
+[[ 1 << -1 ][0] + []][0][1 + [0]]
Definitely more readable now.


Onto the left shift operator:
If you run
Code:
pLog(1<<-1);
it should output the number(-2147483648)
If you want to understand why, read http://stackoverflow.com/questions/1...-in-javascript

So now we have
Code:
+[[-2147483648][0] + []][0][1 + [0]]
The [0] returns the first value from the array, giving us -
Code:
+[-2147483648 + []][0][1 + [0]]
Another important Javascript "feature" is that the + symbol isn't just a mathematical symbol.
Its also used to concatenate two strings.

When you concat anything with an array it treats the array like a string
Code:
pLog("test" + [1]);						//string(test1)
pLog("test" + [1,2]);					//string(test1,2)
pLog([1,4] + [5, 7])					//string(1,45,7)
So -2147483648 + [] actually just converts -2147483648 into the string "-2147483648".
Code:
+["-2147483648"][0][ 1 + [0]]
Notice the last part of the code: [1 + [0]]
If it were [1 + 0] that would evaluate to 1.
However, because [0] is treated as the string "0", it is concatenated onto the number 1. (Have a read through this link if you'd like)
This gives us
Code:
+["-2147483648"][0]["10"]
Now the [0] gives us the first value of the array.
However its not the same as this
Code:
+"-2147483648"["10"]
because in that cause the + converts the string to a number instantly.

Another neat trick is that you can get the Nth character of a string by accessing it as if it were an array.
Code:
var x = "testing123";
pLog(x[3]);								//string(t)
However, in Javascripts arrays aren't really arrays, they're objects.
When you're accessing an object property you can do it two different ways
Code:
var x = {
	randomText: "Hi!",
	randomText2: "Hello!"
};
pLog(x.randomText);
pLog(x["randomText2"]);
The second method is useful when you're trying to access a dynamiclly named property on an object.

But since arrays are actually objects
Code:
var x = [
	"test", 
	"test2", 
	"test3"
];

var y = {
	0: "test",
	1: "test2",
	2: "test3"
};

pLog(x);						//object(test,test2,test3)
pLog(y);						//object([object Object])
pLog(x[1]);						//string(test2)
pLog(y[1]);						//string(test2)
Please note x and y are not the same.

So our current code was
Code:
+["-2147483648"][0]["10"]
We know that the [0] returns the string and the ["10"] returns the 10th character of the string.
Note: either [10] or ["10"] will work
Giving us
Code:
+"8"
Now all that's left is the conversion to a number and we get...
Code:
8
Ta Da!


More reading -
http://stackoverflow.com/questions/7...-the-string-10
https://developer.mozilla.org/en/doc...wise_Operators
http://www.binaryhexconverter.com/bi...imal-converter

Submit "Messing with Javascript" to del.icio.us Submit "Messing with Javascript" to StumbleUpon Submit "Messing with Javascript" to Google Submit "Messing with Javascript" to Digg

Comments