Skip to content

Commit 0be4466

Browse files
committed
why-does-return-the-string-10?rq=1
1 parent a21c001 commit 0be4466

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
### Why does ++[[]][+[]]+[+[]] return the string “10”?
2+
3+
```js
4+
console.log(++[[]][+[]] + [+[]])
5+
```
6+
7+
**Output is 10**
8+
9+
---
10+
11+
#### Explanation-1
12+
13+
If we split it up, the mess is equal to:
14+
15+
++[[]][+[]]
16+
+
17+
[+[]]
18+
19+
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).
20+
21+
Therefore, we can simplify it (`++` has precendence over `+`):
22+
23+
++[[]][0]
24+
+
25+
[0]
26+
27+
Because `[[]][0]` means: get the first element from `[[]]`, it is true that:
28+
29+
`[[]][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.
30+
31+
`++` before its operand means “increment by one and return the incremented result”. So `++[[]][0]` is equivalent to `Number(A) + 1` (or `+A + 1`).
32+
33+
Again, we can simplify the mess into something more legible. Let's substitute `[]` back for `A`:
34+
35+
(+[] + 1)
36+
+
37+
[0]
38+
39+
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`.
40+
41+
- `(+[] + 1) === (+"" + 1)`
42+
- `(+"" + 1) === (0 + 1)`
43+
- `(0 + 1) === 1`
44+
45+
Let's simplify it even more:
46+
47+
1
48+
+
49+
[0]
50+
51+
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.
52+
53+
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_.
54+
55+
"1" + "0" === "10" // Yay!
56+
57+
---
58+
59+
Specification details for `+[]`:
60+
61+
This is quite a maze, but to do `+[]`, first it is being converted to a string because that's what `+` says:
62+
63+
> 11.4.6 Unary + Operator
64+
>
65+
> The unary + operator converts its operand to Number type.
66+
>
67+
> The production UnaryExpression : + UnaryExpression is evaluated as follows:
68+
>
69+
> 1. Let expr be the result of evaluating UnaryExpression.
70+
>
71+
> 2. Return ToNumber(GetValue(expr)).
72+
73+
`ToNumber()` says:
74+
75+
> Object
76+
>
77+
> Apply the following steps:
78+
>
79+
> 1. Let primValue be ToPrimitive(input argument, hint String).
80+
>
81+
> 2. Return ToString(primValue).
82+
83+
`ToPrimitive()` says:
84+
85+
> Object
86+
>
87+
> 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.
88+
89+
`[[DefaultValue]]` says:
90+
91+
> 8.12.8 [[DefaultValue]](hint)
92+
>
93+
> When the [[DefaultValue]] internal method of O is called with hint String, the following steps are taken:
94+
>
95+
> 1. Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".
96+
>
97+
> 2. If IsCallable(toString) is true then,
98+
>
99+
> 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.
100+
>
101+
> b. If str is a primitive value, return str.
102+
103+
The `.toString` of an array says:
104+
105+
> 15.4.4.2 Array.prototype.toString ( )
106+
>
107+
> When the toString method is called, the following steps are taken:
108+
>
109+
> 1. Let array be the result of calling ToObject on the this value.
110+
>
111+
> 2. Let func be the result of calling the [[Get]] internal method of array with argument "join".
112+
>
113+
> 3. If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).
114+
>
115+
> 4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.
116+
117+
So `+[]` comes down to `+""`, because `[].join() === ""`.
118+
119+
Again, the `+` is defined as:
120+
121+
> 11.4.6 Unary + Operator
122+
>
123+
> The unary + operator converts its operand to Number type.
124+
>
125+
> The production UnaryExpression : + UnaryExpression is evaluated as follows:
126+
>
127+
> 1. Let expr be the result of evaluating UnaryExpression.
128+
>
129+
> 2. Return ToNumber(GetValue(expr)).
130+
131+
`ToNumber` is defined for `""` as:
132+
133+
> The MV of StringNumericLiteral ::: [empty] is 0.
134+
135+
So `+"" === 0`, and thus `+[] === 0`.
136+
137+
---

0 commit comments

Comments
 (0)