How is alert(++[[]][+[]]+[+[]]); calculated to 0? - javascript

How is alert(++[[]][+[]]+[+[]]); calculated to 0?
What is this process called so that I can read more about this

The expression ++[[]][+[]]+[+[]] will actually return the string '10'. Let's break it down:
Step 1: +[]
This is an unary plus operator followed by an empty array literal. The unary plus tries to convert the value that follows it into an integer. In this case the value is an array:
+[]; // 0
// This is identical:
Number([]); // 0
The returned value is equivalent to calling [].toString() and then giving that result to Number(). [].toString() will return an empty string (''), and Number('') will return 0.
Array.prototype.toString
The Array object overrides the toString method of Object. For Array objects, the toString method joins the array and returns one string containing each array element separated by commas.
Number.
In a non-constructor context (i.e., without the new operator), Number can be used to perform a type conversion.
So, when we change occurences of +[] to 0 in the source, we get:
++[[]][0] + [0]
Step 2: [[]][0]
This step is a simple array member access operation: An array with one nested (empty) array is first defined, and then that first nested array is accessed with [0], which simply returns []. So, if we replace this part of the expression, we get:
++[] + [0]
Step 3: ++[]
The ++ <value> operator first tries to convert <value> to a number, and then increments that number by 1. The procedure for converting the array to a number in this example occurs the same way as +[] was in step 1: [] is first converted to a string ('' in this case, because the array is empty), and then converted to a number, which again returns 0. Lastly, 0 is incremented by 1, which returns 1. So if we replace this part of the expression, we get:
1 + [0]
Step 4: 1 + [0]
This is the weird part of the story. You would expect this to evaluate to the integer 1, given the information above, but actually it will evaluate to a string '10'. This is because of the 2 steps in the example above for the type conversions of arrays (first to string, then to number). These 2 steps were required because the arrays were always operands of arithmetic operators (i.e. math calculations). The + operator however can serve as both an arithmetic + operator or a string concatenation operator, and the latter always has precedence.
So as soon as [0] is converted to a string, both operands given to the + operator will be converted to a string, because one operand is already a string. If we now replace the expression with converted operands we get the final step in evaluating the expression:
'1' + '0'; // '10'

Related

why does ([]+![])[+!+[]] becomes a in JS? [duplicate]

This is valid and returns the string "10" in JavaScript (more examples here):
console.log(++[[]][+[]]+[+[]])
Why? What is happening here?
If we split it up, the mess is equal to:
++[[]][+[]]
+
[+[]]
In JavaScript, it is true that +[] === 0. + converts something into a number, and in this case it will come down to +"" or 0 (see specification details below).
Therefore, we can simplify it (++ has precendence over +):
++[[]][0]
+
[0]
Because [[]][0] means: get the first element from [[]], it is true that:
[[]][0] returns the inner array ([]). Due to references it's wrong to say [[]][0] === [], but let's call the inner array A to avoid the wrong notation.
++ before its operand means “increment by one and return the incremented result”. So ++[[]][0] is equivalent to Number(A) + 1 (or +A + 1).
Again, we can simplify the mess into something more legible. Let's substitute [] back for A:
(+[] + 1)
+
[0]
Before +[] can coerce the array into the number 0, it needs to be coerced into a string first, which is "", again. Finally, 1 is added, which results in 1.
(+[] + 1) === (+"" + 1)
(+"" + 1) === (0 + 1)
(0 + 1) === 1
Let's simplify it even more:
1
+
[0]
Also, this is true in JavaScript: [0] == "0", because it's joining an array with one element. Joining will concatenate the elements separated by ,. With one element, you can deduce that this logic will result in the first element itself.
In this case, + sees two operands: a number and an array. It’s now trying to coerce the two into the same type. First, the array is coerced into the string "0", next, the number is coerced into a string ("1"). Number + String === String.
"1" + "0" === "10" // Yay!
Specification details for +[]:
This is quite a maze, but to do +[], first it is being converted to a string because that's what + says:
11.4.6 Unary + Operator
The unary + operator converts its operand to Number type.
The production UnaryExpression : + UnaryExpression is evaluated as follows:
Let expr be the result of evaluating UnaryExpression.
Return ToNumber(GetValue(expr)).
ToNumber() says:
Object
Apply the following steps:
Let primValue be ToPrimitive(input argument, hint String).
Return ToString(primValue).
ToPrimitive() says:
Object
Return a default value for the Object. The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType. The behaviour of the [[DefaultValue]] internal method is defined by this specification for all native ECMAScript objects in 8.12.8.
[[DefaultValue]] says:
8.12.8 [[DefaultValue]] (hint)
When the [[DefaultValue]] internal method of O is called with hint String, the following steps are taken:
Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".
If IsCallable(toString) is true then,
a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
b. If str is a primitive value, return str.
The .toString of an array says:
15.4.4.2 Array.prototype.toString ( )
When the toString method is called, the following steps are taken:
Let array be the result of calling ToObject on the this value.
Let func be the result of calling the [[Get]] internal method of array with argument "join".
If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).
Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.
So +[] comes down to +"", because [].join() === "".
Again, the + is defined as:
11.4.6 Unary + Operator
The unary + operator converts its operand to Number type.
The production UnaryExpression : + UnaryExpression is evaluated as follows:
Let expr be the result of evaluating UnaryExpression.
Return ToNumber(GetValue(expr)).
ToNumber is defined for "" as:
The MV of StringNumericLiteral ::: [empty] is 0.
So +"" === 0, and thus +[] === 0.
++[ [] ][+[]] === 1
+[] === 0
++[ [] ][0] === 1
[ +[] ] is [ 0 ]
Then we have a string concatenation:
1 + String([ 0 ]) === 10
The following is adapted from a blog post answering this question that I posted while this question was still closed. Links are to (an HTML copy of) the ECMAScript 3 spec, still the baseline for JavaScript in today's commonly used web browsers.
First, a comment: this kind of expression is never going to show up in any (sane) production environment and is only of any use as an exercise in just how well the reader knows the dirty edges of JavaScript. The general principle that JavaScript operators implicitly convert between types is useful, as are some of the common conversions, but much of the detail in this case is not.
The expression ++[[]][+[]]+[+[]] may initially look rather imposing and obscure, but is actually relatively easy break down into separate expressions. Below I’ve simply added parentheses for clarity; I can assure you they change nothing, but if you want to verify that then feel free to read up about the grouping operator. So, the expression can be more clearly written as
( ++[[]][+[]] ) + ( [+[]] )
Breaking this down, we can simplify by observing that +[] evaluates to 0. To satisfy yourself why this is true, check out the unary + operator and follow the slightly tortuous trail which ends up with ToPrimitive converting the empty array into an empty string, which is then finally converted to 0 by ToNumber. We can now substitute 0 for each instance of +[]:
( ++[[]][0] ) + [0]
Simpler already. As for ++[[]][0], that’s a combination of the prefix increment operator (++), an array literal defining an array with single element that is itself an empty array ([[]]) and a property accessor ([0]) called on the array defined by the array literal.
So, we can simplify [[]][0] to just [] and we have ++[], right? In fact, this is not the case because evaluating ++[] throws an error, which may initially seem confusing. However, a little thought about the nature of ++ makes this clear: it’s used to increment a variable (e.g. ++i) or an object property (e.g. ++obj.count). Not only does it evaluate to a value, it also stores that value somewhere. In the case of ++[], it has nowhere to put the new value (whatever it may be) because there is no reference to an object property or variable to update. In spec terms, this is covered by the internal PutValue operation, which is called by the prefix increment operator.
So then, what does ++[[]][0] do? Well, by similar logic as +[], the inner array is converted to 0 and this value is incremented by 1 to give us a final value of 1. The value of property 0 in the outer array is updated to 1 and the whole expression evaluates to 1.
This leaves us with
1 + [0]
... which is a simple use of the addition operator. Both operands are first converted to primitives and if either primitive value is a string, string concatenation is performed, otherwise numeric addition is performed. [0] converts to "0", so string concatenation is used, producing "10".
As a final aside, something that may not be immediately apparent is that overriding either one of the toString() or valueOf() methods of Array.prototype will change the result of the expression, because both are checked and used if present when converting an object into a primitive value. For example, the following
Array.prototype.toString = function() {
return "foo";
};
++[[]][+[]]+[+[]]
... produces "NaNfoo". Why this happens is left as an exercise for the reader...
Let’s make it simple:
++[[]][+[]]+[+[]] = "10"
var a = [[]][+[]];
var b = [+[]];
// so a == [] and b == [0]
++a;
// then a == 1 and b is still that array [0]
// when you sum the var a and an array, it will sum b as a string just like that:
1 + "0" = "10"
This one evaluates to the same but a bit smaller
+!![]+''+(+[])
[] - is an array is converted that is converted to 0 when you add or subtract from it, so hence +[] = 0
![] - evaluates to false, so hence !![] evaluates to true
+!![] - converts the true to a numeric value that evaluates to true, so in this case 1
+'' - appends an empty string to the expression causing the number to be converted to string
+[] - evaluates to 0
so is evaluates to
+(true) + '' + (0)
1 + '' + 0
"10"
So now you got that, try this one:
_=$=+[],++_+''+$
+[] evaluates to 0
[...] then summing (+ operation) it with anything converts array content to its string representation consisting of elements joined with comma.
Anything other like taking index of array (have grater priority than + operation) is ordinal and is nothing interesting.
Perhaps the shortest possible ways to evaluate an expression as "10" without digits are:
+!+[] + [+[]] // "10"
-~[] + [+[]] // "10"
Explanation
+!+[]:
+[] is evaluated as 0.
!0 is evaluated as true.
+true is evaluated as 1.
-~[] is the same as -(-1) which is evaluated as 1.
[+[]]:
+[] is evaluated as 0
[0] is an array with the single element 0.
Then, JS evaluates the 1 + [0], a Number + Array expression. Then the ECMA specification works: + operator converts both operands to a string by calling the ToPrimitive and ToString abstract operations. It operates as an additive function if both operands of an expression are numbers only. The trick is that arrays easily coerce their elements into a concatenated string representation.
Some examples:
1 + {} // "1[object Object]"
1 + [] // "1"
1 + new Date() // "1Wed Jun 19 2013 12:13:25 GMT+0400 (Caucasus Standard Time)"
[] + [] // ""
[1] + [2] // "12"
{} + {} // "[object Object][object Object]" ¹
{a:1} + {b:2} // "[object Object][object Object]" ¹
[1, {}] + [2, {}] // "1,[object Object]2,[object Object]"
¹: Note that each line is evaluated in an expression context. The first {…} is an object literal, not a block, as would be the case in a statement context. In a REPL, you may see {} + {} resulting in NaN, because most REPLs operate in a statement context; here, the first {} is a block, and the code is equivalent to {}; +{};, with the final expression statement (whose value becomes the result of the completion record) is NaN because the unary + coerces the object to a number.
++[[]][+[]]+[+[]]
^^^
|
v
++[[]][+[]]+[0]
^^^
|
v
++[[]][0]+[0]
^^^^^^^
|
v
++[]+[0]
^^^
|
v
++[]+"0"
^^^^
|
v
++0+"0"
^^^
|
v
1+"0"
^^^^^
|
v
"10"
The + operator coerces any non-number operand via .valueOf(). If that doesn't return a number then .toString() is invoked.
We can verify this simply with:
const x = [], y = [];
x.valueOf = () => (console.log('x.valueOf() has been called'), y.valueOf());
x.toString = () => (console.log('x.toString() has been called'), y.toString());
console.log(`+x -> ${+x}`);
So +[] is the same as coercing "" into a number which is 0.
If any operand is a string then + concatenates.
Step by steps of that, + turn value to a number and if you add to an empty array +[]...as it's empty and is equal to 0, it will
So from there, now look into your code, it's ++[[]][+[]]+[+[]]...
And there is plus between them ++[[]][+[]] + [+[]]
So these [+[]] will return [0] as they have an empty array which gets converted to 0 inside the other array...
So as imagine, the first value is a 2-dimensional array with one array inside... so [[]][+[]] will be equal to [[]][0] which will return []...
And at the end ++ convert it and increase it to 1...
So you can imagine, 1 + "0" will be "10"...
Unary plus given string converts to number
Increment operator given string converts and increments by 1
[] == ''. Empty String
+'' or +[] evaluates 0.
++[[]][+[]]+[+[]] = 10
++[''][0] + [0] : First part is gives zeroth element of the array which is empty string
1+0
10

[]+(-~{}-~{}-~{}-~{})+(-~{}-~{}) [duplicate]

This question already has answers here:
Why does ++[[]][+[]]+[+[]] return the string "10"?
(10 answers)
(![]+[])[+[]]... Explain why this works
(1 answer)
Closed 9 years ago.
While reading this article posted on dzone I found a snippet of JavaScript originally posted on Twitter by Marcus Lagergren.
The following code apparently prints the string "fail"
(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];
This involves implicit type casting and I'm trying to understand how exactly this line is interpreted.
I've isolated each character
(![]+[])[+[]] prints "f"
(![]+[])[+!+[]] prints "a"
([![]]+[][[]])[+!+[]+[+[]]] prints "i"
(![]+[])[!+[]+!+[]] prints "l"
I've also managed to break down the expressions returning each letter apart from "i"
letter "f"
![] an empty array is an Object, which according to ECMAScript documentation, point 9.2 evaluates to true when converted to a boolean so this is false
false+[] as per Point 11.6.1 both arguments of the binary + operator get converted to String, therefore we get "false"+"", which evaluates "false"
+[] a unary plus operator causes a ToNumber conversion followed by a ToPrimitive conversion if the argument is an Object. The result of such conversion is determined by calling the [[DefaultValue]] internal method of the object. In case of an empty array, it defaults to 0.
(ECMAScript Documentation, sections: 11.4.6, 9.3, 9.1 )
"false"[0] we're accessing the character at index 0, hence the "f"
letter "a"
Same story, the only difference here are additional conversions in the part in square brackets (which evaluates to a number to point at another character in the string "false"), triggered by the use of unary + and ! operators.
+[] evaluates to 0, as explained above.
!0 evaluates to true as defined in Section 9.2 and Section 11.4.9. First, 0 is converted to a boolean false and then the operator inverts the value.
+true again, the unary plus triggers a ToNumber conversion, which returns a 1 for binary true
(Section 11.4.6 and 9.3)
"false"[1] returns the second character in the string, which is "a"
letter "l"
!+[] evaluates to true as explained above
true+true using the binary + on primitives triggers a ToNumber conversion. In case of true, its result is 1 and 1+1 equals 2
"false"[2] - self explanatory
letter "i"
What leaves me stumped is the letter "i". I can see that the second part (in square brackets) evaluates to the string "10" and that the first part (in parentheses) returns "falseundefined" but I can't make heads or tails of how this is happening. Could someone explain it step by step? Especially the magic that happens with square brackets? (arrays and array access)
If possible, I'd like each step to contain a link to the underlying ECMAScript rules.
What I find the most cryptic is this part: [][[]]
Your cryptic part isn't all that cryptic if you rewrite it a little:
[]['']
[] will be coerced into a string because it isn't an integer, so you're looking for a property of [] with the name '' (an empty string). You'll just get undefined, as there is no property with that name.
As for the actual letter, break the expression up into the two main components:
The string ([![]]+[][[]]):
[![]] is [false].
[][[]] is undefined.
Add them together and you get "falseundefined".
And the index: [+!+[]+[+[]]]. Some whitespace and parentheses will make the operations much clearer: [+(!(+[])) + [+[]]]:
[+[]] is [0].
+[] coerces [] to an integer, so you get 0.
!+[] coerces 0 to a boolean and negates it, so you get true.
+!+[] coerces true to an integer, so you get 1.
Add them together, and you get ["10"].
When using a string to access the properties of the array and the string happens to be an element of the array, the string is coerced into an integer and you get back the actual element of the array:
> [1, 2, 3]["0"]
1
> [1, 2, 3]["1"]
2
So your final result is:
> "falseundefined"["10"]
"i"
Read this answer for an explanation of the [false] + undefined part.
([![]]+[][[]])[+!+[]+[+[]]] has two parts :
([![]]+[][[]]) and the other which you found yourself.
![] returns false. Then we use [...] to get the .toString() behavior of +.
([]+[] is the same as [].toString()+[].toString())
the [][[]] is undefined because we're trying to access the index [] (or [].toString(), which is '') of [] which is undefined.
Sorry for the previous answered, I misread your comment totally.

Javascript ++[[]][+[]]+[+[]] === "10" [duplicate]

This is valid and returns the string "10" in JavaScript (more examples here):
console.log(++[[]][+[]]+[+[]])
Why? What is happening here?
If we split it up, the mess is equal to:
++[[]][+[]]
+
[+[]]
In JavaScript, it is true that +[] === 0. + converts something into a number, and in this case it will come down to +"" or 0 (see specification details below).
Therefore, we can simplify it (++ has precendence over +):
++[[]][0]
+
[0]
Because [[]][0] means: get the first element from [[]], it is true that:
[[]][0] returns the inner array ([]). Due to references it's wrong to say [[]][0] === [], but let's call the inner array A to avoid the wrong notation.
++ before its operand means “increment by one and return the incremented result”. So ++[[]][0] is equivalent to Number(A) + 1 (or +A + 1).
Again, we can simplify the mess into something more legible. Let's substitute [] back for A:
(+[] + 1)
+
[0]
Before +[] can coerce the array into the number 0, it needs to be coerced into a string first, which is "", again. Finally, 1 is added, which results in 1.
(+[] + 1) === (+"" + 1)
(+"" + 1) === (0 + 1)
(0 + 1) === 1
Let's simplify it even more:
1
+
[0]
Also, this is true in JavaScript: [0] == "0", because it's joining an array with one element. Joining will concatenate the elements separated by ,. With one element, you can deduce that this logic will result in the first element itself.
In this case, + sees two operands: a number and an array. It’s now trying to coerce the two into the same type. First, the array is coerced into the string "0", next, the number is coerced into a string ("1"). Number + String === String.
"1" + "0" === "10" // Yay!
Specification details for +[]:
This is quite a maze, but to do +[], first it is being converted to a string because that's what + says:
11.4.6 Unary + Operator
The unary + operator converts its operand to Number type.
The production UnaryExpression : + UnaryExpression is evaluated as follows:
Let expr be the result of evaluating UnaryExpression.
Return ToNumber(GetValue(expr)).
ToNumber() says:
Object
Apply the following steps:
Let primValue be ToPrimitive(input argument, hint String).
Return ToString(primValue).
ToPrimitive() says:
Object
Return a default value for the Object. The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType. The behaviour of the [[DefaultValue]] internal method is defined by this specification for all native ECMAScript objects in 8.12.8.
[[DefaultValue]] says:
8.12.8 [[DefaultValue]] (hint)
When the [[DefaultValue]] internal method of O is called with hint String, the following steps are taken:
Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".
If IsCallable(toString) is true then,
a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
b. If str is a primitive value, return str.
The .toString of an array says:
15.4.4.2 Array.prototype.toString ( )
When the toString method is called, the following steps are taken:
Let array be the result of calling ToObject on the this value.
Let func be the result of calling the [[Get]] internal method of array with argument "join".
If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).
Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.
So +[] comes down to +"", because [].join() === "".
Again, the + is defined as:
11.4.6 Unary + Operator
The unary + operator converts its operand to Number type.
The production UnaryExpression : + UnaryExpression is evaluated as follows:
Let expr be the result of evaluating UnaryExpression.
Return ToNumber(GetValue(expr)).
ToNumber is defined for "" as:
The MV of StringNumericLiteral ::: [empty] is 0.
So +"" === 0, and thus +[] === 0.
++[ [] ][+[]] === 1
+[] === 0
++[ [] ][0] === 1
[ +[] ] is [ 0 ]
Then we have a string concatenation:
1 + String([ 0 ]) === 10
The following is adapted from a blog post answering this question that I posted while this question was still closed. Links are to (an HTML copy of) the ECMAScript 3 spec, still the baseline for JavaScript in today's commonly used web browsers.
First, a comment: this kind of expression is never going to show up in any (sane) production environment and is only of any use as an exercise in just how well the reader knows the dirty edges of JavaScript. The general principle that JavaScript operators implicitly convert between types is useful, as are some of the common conversions, but much of the detail in this case is not.
The expression ++[[]][+[]]+[+[]] may initially look rather imposing and obscure, but is actually relatively easy break down into separate expressions. Below I’ve simply added parentheses for clarity; I can assure you they change nothing, but if you want to verify that then feel free to read up about the grouping operator. So, the expression can be more clearly written as
( ++[[]][+[]] ) + ( [+[]] )
Breaking this down, we can simplify by observing that +[] evaluates to 0. To satisfy yourself why this is true, check out the unary + operator and follow the slightly tortuous trail which ends up with ToPrimitive converting the empty array into an empty string, which is then finally converted to 0 by ToNumber. We can now substitute 0 for each instance of +[]:
( ++[[]][0] ) + [0]
Simpler already. As for ++[[]][0], that’s a combination of the prefix increment operator (++), an array literal defining an array with single element that is itself an empty array ([[]]) and a property accessor ([0]) called on the array defined by the array literal.
So, we can simplify [[]][0] to just [] and we have ++[], right? In fact, this is not the case because evaluating ++[] throws an error, which may initially seem confusing. However, a little thought about the nature of ++ makes this clear: it’s used to increment a variable (e.g. ++i) or an object property (e.g. ++obj.count). Not only does it evaluate to a value, it also stores that value somewhere. In the case of ++[], it has nowhere to put the new value (whatever it may be) because there is no reference to an object property or variable to update. In spec terms, this is covered by the internal PutValue operation, which is called by the prefix increment operator.
So then, what does ++[[]][0] do? Well, by similar logic as +[], the inner array is converted to 0 and this value is incremented by 1 to give us a final value of 1. The value of property 0 in the outer array is updated to 1 and the whole expression evaluates to 1.
This leaves us with
1 + [0]
... which is a simple use of the addition operator. Both operands are first converted to primitives and if either primitive value is a string, string concatenation is performed, otherwise numeric addition is performed. [0] converts to "0", so string concatenation is used, producing "10".
As a final aside, something that may not be immediately apparent is that overriding either one of the toString() or valueOf() methods of Array.prototype will change the result of the expression, because both are checked and used if present when converting an object into a primitive value. For example, the following
Array.prototype.toString = function() {
return "foo";
};
++[[]][+[]]+[+[]]
... produces "NaNfoo". Why this happens is left as an exercise for the reader...
Let’s make it simple:
++[[]][+[]]+[+[]] = "10"
var a = [[]][+[]];
var b = [+[]];
// so a == [] and b == [0]
++a;
// then a == 1 and b is still that array [0]
// when you sum the var a and an array, it will sum b as a string just like that:
1 + "0" = "10"
This one evaluates to the same but a bit smaller
+!![]+''+(+[])
[] - is an array is converted that is converted to 0 when you add or subtract from it, so hence +[] = 0
![] - evaluates to false, so hence !![] evaluates to true
+!![] - converts the true to a numeric value that evaluates to true, so in this case 1
+'' - appends an empty string to the expression causing the number to be converted to string
+[] - evaluates to 0
so is evaluates to
+(true) + '' + (0)
1 + '' + 0
"10"
So now you got that, try this one:
_=$=+[],++_+''+$
+[] evaluates to 0
[...] then summing (+ operation) it with anything converts array content to its string representation consisting of elements joined with comma.
Anything other like taking index of array (have grater priority than + operation) is ordinal and is nothing interesting.
Perhaps the shortest possible ways to evaluate an expression as "10" without digits are:
+!+[] + [+[]] // "10"
-~[] + [+[]] // "10"
Explanation
+!+[]:
+[] is evaluated as 0.
!0 is evaluated as true.
+true is evaluated as 1.
-~[] is the same as -(-1) which is evaluated as 1.
[+[]]:
+[] is evaluated as 0
[0] is an array with the single element 0.
Then, JS evaluates the 1 + [0], a Number + Array expression. Then the ECMA specification works: + operator converts both operands to a string by calling the ToPrimitive and ToString abstract operations. It operates as an additive function if both operands of an expression are numbers only. The trick is that arrays easily coerce their elements into a concatenated string representation.
Some examples:
1 + {} // "1[object Object]"
1 + [] // "1"
1 + new Date() // "1Wed Jun 19 2013 12:13:25 GMT+0400 (Caucasus Standard Time)"
[] + [] // ""
[1] + [2] // "12"
{} + {} // "[object Object][object Object]" ¹
{a:1} + {b:2} // "[object Object][object Object]" ¹
[1, {}] + [2, {}] // "1,[object Object]2,[object Object]"
¹: Note that each line is evaluated in an expression context. The first {…} is an object literal, not a block, as would be the case in a statement context. In a REPL, you may see {} + {} resulting in NaN, because most REPLs operate in a statement context; here, the first {} is a block, and the code is equivalent to {}; +{};, with the final expression statement (whose value becomes the result of the completion record) is NaN because the unary + coerces the object to a number.
++[[]][+[]]+[+[]]
^^^
|
v
++[[]][+[]]+[0]
^^^
|
v
++[[]][0]+[0]
^^^^^^^
|
v
++[]+[0]
^^^
|
v
++[]+"0"
^^^^
|
v
++0+"0"
^^^
|
v
1+"0"
^^^^^
|
v
"10"
The + operator coerces any non-number operand via .valueOf(). If that doesn't return a number then .toString() is invoked.
We can verify this simply with:
const x = [], y = [];
x.valueOf = () => (console.log('x.valueOf() has been called'), y.valueOf());
x.toString = () => (console.log('x.toString() has been called'), y.toString());
console.log(`+x -> ${+x}`);
So +[] is the same as coercing "" into a number which is 0.
If any operand is a string then + concatenates.
Step by steps of that, + turn value to a number and if you add to an empty array +[]...as it's empty and is equal to 0, it will
So from there, now look into your code, it's ++[[]][+[]]+[+[]]...
And there is plus between them ++[[]][+[]] + [+[]]
So these [+[]] will return [0] as they have an empty array which gets converted to 0 inside the other array...
So as imagine, the first value is a 2-dimensional array with one array inside... so [[]][+[]] will be equal to [[]][0] which will return []...
And at the end ++ convert it and increase it to 1...
So you can imagine, 1 + "0" will be "10"...
Unary plus given string converts to number
Increment operator given string converts and increments by 1
[] == ''. Empty String
+'' or +[] evaluates 0.
++[[]][+[]]+[+[]] = 10
++[''][0] + [0] : First part is gives zeroth element of the array which is empty string
1+0
10

Javascript Compiler behavior - double plus for array of empty array and array of zero is.. ONE

My question may be already answered, but I could not find it not in Search Engines google or bing doesn't like '+' (plus) sign in search request.
Anyway, why this is zero
+[[]][0] // = 0
and this is one
++[[]][0] // = 1
UPD:
Michael Berkowski have a good answer, but I steal don't understand one thing
if [[]][0] evaluates to an empty array, then why ++[] is ReferenceError: Invalid left-hand side expression in prefix operation
UPD2:
now I get it.. it seems I was trying to type ++0 in console and getting an Error, but I should be using var a = 0; ++a
This is best explored by breaking down the way its components evaluate.
[[]][0] alone evaluates to the empty array []. By adding + in front, you cast its string representation to an integer 0 (like saying +4 or -3) via a unary positive operator. +0 is just 0.
++ as a numeric operator, also casts the empty string to an integer 0, but applies its operation (the prefix increment) resulting 1.
[[]][0]
// [] empty array
[[]][0].toString()
// ""
// Unary + casts the empty string to an integer
+("")
// 0
// Prefix increment on an empty string results in 1 (increments the 0)
var emptyString = "";
++emptyString;
// 1

Why does ++[[]][+[]]+[+[]] return the string "10"?

This is valid and returns the string "10" in JavaScript (more examples here):
console.log(++[[]][+[]]+[+[]])
Why? What is happening here?
If we split it up, the mess is equal to:
++[[]][+[]]
+
[+[]]
In JavaScript, it is true that +[] === 0. + converts something into a number, and in this case it will come down to +"" or 0 (see specification details below).
Therefore, we can simplify it (++ has precendence over +):
++[[]][0]
+
[0]
Because [[]][0] means: get the first element from [[]], it is true that:
[[]][0] returns the inner array ([]). Due to references it's wrong to say [[]][0] === [], but let's call the inner array A to avoid the wrong notation.
++ before its operand means “increment by one and return the incremented result”. So ++[[]][0] is equivalent to Number(A) + 1 (or +A + 1).
Again, we can simplify the mess into something more legible. Let's substitute [] back for A:
(+[] + 1)
+
[0]
Before +[] can coerce the array into the number 0, it needs to be coerced into a string first, which is "", again. Finally, 1 is added, which results in 1.
(+[] + 1) === (+"" + 1)
(+"" + 1) === (0 + 1)
(0 + 1) === 1
Let's simplify it even more:
1
+
[0]
Also, this is true in JavaScript: [0] == "0", because it's joining an array with one element. Joining will concatenate the elements separated by ,. With one element, you can deduce that this logic will result in the first element itself.
In this case, + sees two operands: a number and an array. It’s now trying to coerce the two into the same type. First, the array is coerced into the string "0", next, the number is coerced into a string ("1"). Number + String === String.
"1" + "0" === "10" // Yay!
Specification details for +[]:
This is quite a maze, but to do +[], first it is being converted to a string because that's what + says:
11.4.6 Unary + Operator
The unary + operator converts its operand to Number type.
The production UnaryExpression : + UnaryExpression is evaluated as follows:
Let expr be the result of evaluating UnaryExpression.
Return ToNumber(GetValue(expr)).
ToNumber() says:
Object
Apply the following steps:
Let primValue be ToPrimitive(input argument, hint String).
Return ToString(primValue).
ToPrimitive() says:
Object
Return a default value for the Object. The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType. The behaviour of the [[DefaultValue]] internal method is defined by this specification for all native ECMAScript objects in 8.12.8.
[[DefaultValue]] says:
8.12.8 [[DefaultValue]] (hint)
When the [[DefaultValue]] internal method of O is called with hint String, the following steps are taken:
Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".
If IsCallable(toString) is true then,
a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
b. If str is a primitive value, return str.
The .toString of an array says:
15.4.4.2 Array.prototype.toString ( )
When the toString method is called, the following steps are taken:
Let array be the result of calling ToObject on the this value.
Let func be the result of calling the [[Get]] internal method of array with argument "join".
If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).
Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.
So +[] comes down to +"", because [].join() === "".
Again, the + is defined as:
11.4.6 Unary + Operator
The unary + operator converts its operand to Number type.
The production UnaryExpression : + UnaryExpression is evaluated as follows:
Let expr be the result of evaluating UnaryExpression.
Return ToNumber(GetValue(expr)).
ToNumber is defined for "" as:
The MV of StringNumericLiteral ::: [empty] is 0.
So +"" === 0, and thus +[] === 0.
++[ [] ][+[]] === 1
+[] === 0
++[ [] ][0] === 1
[ +[] ] is [ 0 ]
Then we have a string concatenation:
1 + String([ 0 ]) === 10
The following is adapted from a blog post answering this question that I posted while this question was still closed. Links are to (an HTML copy of) the ECMAScript 3 spec, still the baseline for JavaScript in today's commonly used web browsers.
First, a comment: this kind of expression is never going to show up in any (sane) production environment and is only of any use as an exercise in just how well the reader knows the dirty edges of JavaScript. The general principle that JavaScript operators implicitly convert between types is useful, as are some of the common conversions, but much of the detail in this case is not.
The expression ++[[]][+[]]+[+[]] may initially look rather imposing and obscure, but is actually relatively easy break down into separate expressions. Below I’ve simply added parentheses for clarity; I can assure you they change nothing, but if you want to verify that then feel free to read up about the grouping operator. So, the expression can be more clearly written as
( ++[[]][+[]] ) + ( [+[]] )
Breaking this down, we can simplify by observing that +[] evaluates to 0. To satisfy yourself why this is true, check out the unary + operator and follow the slightly tortuous trail which ends up with ToPrimitive converting the empty array into an empty string, which is then finally converted to 0 by ToNumber. We can now substitute 0 for each instance of +[]:
( ++[[]][0] ) + [0]
Simpler already. As for ++[[]][0], that’s a combination of the prefix increment operator (++), an array literal defining an array with single element that is itself an empty array ([[]]) and a property accessor ([0]) called on the array defined by the array literal.
So, we can simplify [[]][0] to just [] and we have ++[], right? In fact, this is not the case because evaluating ++[] throws an error, which may initially seem confusing. However, a little thought about the nature of ++ makes this clear: it’s used to increment a variable (e.g. ++i) or an object property (e.g. ++obj.count). Not only does it evaluate to a value, it also stores that value somewhere. In the case of ++[], it has nowhere to put the new value (whatever it may be) because there is no reference to an object property or variable to update. In spec terms, this is covered by the internal PutValue operation, which is called by the prefix increment operator.
So then, what does ++[[]][0] do? Well, by similar logic as +[], the inner array is converted to 0 and this value is incremented by 1 to give us a final value of 1. The value of property 0 in the outer array is updated to 1 and the whole expression evaluates to 1.
This leaves us with
1 + [0]
... which is a simple use of the addition operator. Both operands are first converted to primitives and if either primitive value is a string, string concatenation is performed, otherwise numeric addition is performed. [0] converts to "0", so string concatenation is used, producing "10".
As a final aside, something that may not be immediately apparent is that overriding either one of the toString() or valueOf() methods of Array.prototype will change the result of the expression, because both are checked and used if present when converting an object into a primitive value. For example, the following
Array.prototype.toString = function() {
return "foo";
};
++[[]][+[]]+[+[]]
... produces "NaNfoo". Why this happens is left as an exercise for the reader...
Let’s make it simple:
++[[]][+[]]+[+[]] = "10"
var a = [[]][+[]];
var b = [+[]];
// so a == [] and b == [0]
++a;
// then a == 1 and b is still that array [0]
// when you sum the var a and an array, it will sum b as a string just like that:
1 + "0" = "10"
This one evaluates to the same but a bit smaller
+!![]+''+(+[])
[] - is an array is converted that is converted to 0 when you add or subtract from it, so hence +[] = 0
![] - evaluates to false, so hence !![] evaluates to true
+!![] - converts the true to a numeric value that evaluates to true, so in this case 1
+'' - appends an empty string to the expression causing the number to be converted to string
+[] - evaluates to 0
so is evaluates to
+(true) + '' + (0)
1 + '' + 0
"10"
So now you got that, try this one:
_=$=+[],++_+''+$
+[] evaluates to 0
[...] then summing (+ operation) it with anything converts array content to its string representation consisting of elements joined with comma.
Anything other like taking index of array (have grater priority than + operation) is ordinal and is nothing interesting.
Perhaps the shortest possible ways to evaluate an expression as "10" without digits are:
+!+[] + [+[]] // "10"
-~[] + [+[]] // "10"
Explanation
+!+[]:
+[] is evaluated as 0.
!0 is evaluated as true.
+true is evaluated as 1.
-~[] is the same as -(-1) which is evaluated as 1.
[+[]]:
+[] is evaluated as 0
[0] is an array with the single element 0.
Then, JS evaluates the 1 + [0], a Number + Array expression. Then the ECMA specification works: + operator converts both operands to a string by calling the ToPrimitive and ToString abstract operations. It operates as an additive function if both operands of an expression are numbers only. The trick is that arrays easily coerce their elements into a concatenated string representation.
Some examples:
1 + {} // "1[object Object]"
1 + [] // "1"
1 + new Date() // "1Wed Jun 19 2013 12:13:25 GMT+0400 (Caucasus Standard Time)"
[] + [] // ""
[1] + [2] // "12"
{} + {} // "[object Object][object Object]" ¹
{a:1} + {b:2} // "[object Object][object Object]" ¹
[1, {}] + [2, {}] // "1,[object Object]2,[object Object]"
¹: Note that each line is evaluated in an expression context. The first {…} is an object literal, not a block, as would be the case in a statement context. In a REPL, you may see {} + {} resulting in NaN, because most REPLs operate in a statement context; here, the first {} is a block, and the code is equivalent to {}; +{};, with the final expression statement (whose value becomes the result of the completion record) is NaN because the unary + coerces the object to a number.
++[[]][+[]]+[+[]]
^^^
|
v
++[[]][+[]]+[0]
^^^
|
v
++[[]][0]+[0]
^^^^^^^
|
v
++[]+[0]
^^^
|
v
++[]+"0"
^^^^
|
v
++0+"0"
^^^
|
v
1+"0"
^^^^^
|
v
"10"
The + operator coerces any non-number operand via .valueOf(). If that doesn't return a number then .toString() is invoked.
We can verify this simply with:
const x = [], y = [];
x.valueOf = () => (console.log('x.valueOf() has been called'), y.valueOf());
x.toString = () => (console.log('x.toString() has been called'), y.toString());
console.log(`+x -> ${+x}`);
So +[] is the same as coercing "" into a number which is 0.
If any operand is a string then + concatenates.
Step by steps of that, + turn value to a number and if you add to an empty array +[]...as it's empty and is equal to 0, it will
So from there, now look into your code, it's ++[[]][+[]]+[+[]]...
And there is plus between them ++[[]][+[]] + [+[]]
So these [+[]] will return [0] as they have an empty array which gets converted to 0 inside the other array...
So as imagine, the first value is a 2-dimensional array with one array inside... so [[]][+[]] will be equal to [[]][0] which will return []...
And at the end ++ convert it and increase it to 1...
So you can imagine, 1 + "0" will be "10"...
Unary plus given string converts to number
Increment operator given string converts and increments by 1
[] == ''. Empty String
+'' or +[] evaluates 0.
++[[]][+[]]+[+[]] = 10
++[''][0] + [0] : First part is gives zeroth element of the array which is empty string
1+0
10

Categories