Edit: At the bottom I've added what I've figured out since I wrote this.
Today I sat down and figured out why you get this result in JavaScript
(! + [] + [] + ![]).length
> 9
So I sat down with the js console and tried to figure things out. There were a lot of this going on:
(!"")
>true
(![])
>false
(!+[])
>true
(!+[]+[])
>"true"
(+[]+"2")
>"02"
([]+"2")
>"2"
What I have come up with, and I might be totally off on some of these so please correct anything that doesn't look right, is the following.
- JavaScript does operations from right to left.
- The + operand first tries to add the left to the right, if that isn't possible it tries to convert the operand on the right to a number and if it can't do that it converts it to a string. If there is something to the left of the + it adds them together, and if it can't it sticks around. If there is nothing to the left it goes away.
- The ! operand converts the operand to the right to a boolean and then reverts it. Only the following values are the same as false as booleans:
false
0
""
null
NaN
undefined
All other values is not false and thus true.
So now it goes something like this:
// We start with
(! + [] + [] + ![]).length // Remember that we are going from right to left starting
// with the operation before doing -length
![] === false // ! converts the content of [] to true, since it's not part of
// the false group above, and then reverts it.
+ === + // the + is lonely so far with no operand to the right but sticks
// around since it has something on the left.
[]+[] === "" // The contents of [] can't be added or converted to a number so
// the right operand becomes a string. There's still something to
// the left so the + stays.
!+[] === true // This the same as !+0 since +[] is 0
// Now we got:
("false" + "" + false).length
""+false === "false" // + adds "" to false. It then sticks around.
"true" + "" === "true" // The + stays after adding "true" to ""
// ---
("true"++"false")
+"false" ==== "false" // + has nothing but an operand to the left so it goes away.
true + "" === "true" // + adds them together and stays
// ---
("true"+"false")
"true" + "false" === "truefalse" // + still stays
// ---
(+"truefalse")
+"truefalse" === "truefalse" // + has nothing to do after this so it goes away
// ---
("truefalse") // The operation is done so now we are left with what's outside.
"truefalse".length === 9
Yes, I did go through every step, even those that seems pointless. I'm not at all sure this is how it works but it is what seems to happen to me.
Thoughts?
Edit:
After comments and looking at the documentation this is now how I figure things going.
((!(+[]))+[]+(![]))
Unary operators are going right to left thus !+[] becomes +[] -> !0 === true.
Top comments (19)
In some cases it does, but not in this case. The reason you see behaviour that may appear to be right-to-left evaluation is because of operator precedence, where the unary
!
has a higher precedence than the binary+
.+
actually evaluates from left to right, so more verbosely parenthesized, it looks like this:Evaluating this parenthesized form step-by-step, we get this:
The first + is unary, right?
Indeed it is.
If I'm not sure what's going on with the JS code, I use ASTexplorer to look at the code with the compiler's eyes. It converts a code string into the tree of instructions to be executed by the compiler step by step.
But sometimes text representation of a tree is not expressive enough, so I built a little tool which visualizes an AST tree.
For
(! + [] + [] + ![]).length
AST in graph form looks like this:In runtime calculations starts from the bottom left and flow to the top.
love this!
This is also equal to 9 but for a very different reason
This one too but for yet another reason
Standing on the shoulders of giants.
You can stand on your own shoulders this was perfect
Interesting breakdown. I might have missed something but I think "truefalls" should be "truefalse".
Indeed it should =D That's dyslexia for ya.
Ain't that the truef.
It is a great observation , typecasting in JS is weird. This is the reason I love this platform.
AWESOME INTERVIEW QUESTION!!!
jajaja many brains will explode
Totally greatly interesting.
Thank you for your great post.
The behaviors seem a bit strange and are beautiful 😆
Hi.
This is very well documented in the Boolean coercion abstract operation by ECMAScript language.
So, there are two operations that you may check out.
Is this ease of programming?
Does this have anything to do with the esoteric version of JS? en.m.wikipedia.org/wiki/JSFuck