Reputation: 1063
I'm looking at ECMA-262 grammar for a definition of the next code bellow:
const v = (! + [] + []);
const c = (false + []);
console.log(v);
console.log(c);
What is BEHIND it?
Until now I did not find anything helpful, does anyone know why it gives those results or have references about it?
Upvotes: 3
Views: 297
Reputation: 10967
This is because when you try to apply an operator to different data structure JavaScript engine applies coercion.
In the first case what it does is :
Convert first [] to primitive, which is performed by invoking toString() method of array. The toString method joins all the array values to a string. If you wold have something like (false + [1,2,3])
you would get : false1,2,3
The second step is to bring the boolean in the String context
Now that we have all the values in the same datastructure, it will simply concatenate all of them
In your case (! + [] + [])
is evaluated to 'true' which has the length of 4.
The book You Don't Know JS: Types & Grammar is a gem for understanding all these kind of weird operations JavaScript engine does.
EDIT: As Felix Kling was suggesting ! operator has a different role in the evaluation of (! + [] + [])
.
In this case what happens is that :
! + []
is evaluated to true. This is because ! + []
puts them in a Boolean context where [toNumber] operation is applied on [] which is 0
and !0
is true
true + []
is evaluated to 'true'
. This is because when you try to add a boolean with an object (array is derived from object) [toString] operation is applied to both items.
Upvotes: 5
Reputation: 28573
const v = (! + [] + []);
const c = (false + []);
console.log(v);
console.log(c);
If you take out the .length
, you see that the results are:
true
and false
and that these (the results of the +
operations) are not arrays but strings, and true
is 4 characters long and false
is 5.
Using your link above, it looks like this is at least partly relevant:
12.7.3 The Addition operator ( + )
NOTE The addition operator either performs string concatenation or numeric addition.
Upvotes: 2
Reputation: 17190
Actually, for understand why you are getting that result, you have to think how the expression is evaluated (i.e, in what order?). If we observe your first expression:
const v = (! + [] + []);
we can see that there exists one logical operator (the logical NOT !
), one unary operator (+
) and one arithmetic operator, actually the addition +
. If we take into account the order of evaluation of that expression, we can write it like this:
const v = ( (!(+[])) + [] );
Now, the first expression evaluated here is +[]
, and from the documentation of the unary plus operator you get:
The unary plus operator precedes its operand and evaluates to its operand but attempts to convert it into a number, if it isn't already...
Actually, the previous evaluation results in 0
(a coercion occurs in where the empty array is casted to number type) as you can check on next example:
console.log(+[]);
So now, the expression is reduced to
const v = ( (!0) + [] );
Again, reading some documentation of this logical not operator you can found:
Returns false if its single operand can be converted to true; otherwise, returns true.
So, !0
is reduced to true
(another coercion occurs in where the number zero is casted to boolean type) as you can check on next example:
console.log(!0);
Now, we have next expression where the addition operator comes into play:
const v = ( true + [] );
The addition operator produces the sum of numeric operands or string concatenation.
In this case, the operator will do string concatenation since the operands aren't numbers. So, here is where a new coercion (basically a implicit cast of types) takes places again, because it need to convert both of the operand to strings:
true
is converted to string "true"
using the method toString()
of the Boolean type.[]
is converted to the empty string ""
using the available toString()
method of Array type.And finally, our expression is reduce to:
const v = "true" + ""; // or simply "true".
const v = (! + [] + []);
console.log("value: " + v, "type: " + typeof(v));
The second expression should be easy to analyze for your own now, since it is a simplified version of the first one.
Upvotes: 3