问题描述
这是有效的,并在 JavaScript 中返回字符串 "10"
(更多例子在这里):
console.log(++[[]][+[]]+[+[]])
为什么?这里发生了什么?
如果我们把它分开,就等于:
++[[]][+[]]+[+[]]
在 JavaScript 中,+[] === 0
确实如此.+
将某些内容转换为数字,在这种情况下,它将归结为 +""
或 0
(请参阅下面的规范详细信息).
因此,我们可以简化它(++
优先于 +
):
++[[]][0]+[0]
因为[[]][0]
的意思是:从[[]]
中获取第一个元素,所以:
[[]][0]
返回内部数组([]
).由于引用,说[[]][0] === []
是错误的,但让我们调用内部数组A
以避免错误的表示法.
++
在它的操作数之前表示加一并返回增加的结果".所以++[[]][0]
等价于Number(A) + 1
(或+A + 1
).>
同样,我们可以将混乱简化为更清晰的内容.让我们用 []
替换回 A
:
(+[] + 1)+[0]
在+[]
可以将数组强制为数字0
之前,需要先将其强制为字符串,即""
再说一遍.最后,添加1
,结果为1
.
(+[] + 1) === (+"" + 1)
(+"" + 1) === (0 + 1)
(0 + 1) === 1
让我们进一步简化它:
1+[0]
此外,这在 JavaScript 中也是正确的:[0] == "0"
,因为它连接了一个具有一个元素的数组.Join 将连接由 ,
分隔的元素.对于一个元素,您可以推断出此逻辑将生成第一个元素本身.
在这种情况下,+
看到两个操作数:一个数字和一个数组.它现在试图将两者强制为同一类型.首先将数组强制转换为字符串"0"
,然后将数字强制转换为字符串("1"
).数字 +
String ===
String.
"1" + "0" === "10"//耶!
+[]
的详细说明:
这是一个相当大的迷宫,但是要做到+[]
,首先它被转换成一个字符串,因为这就是+
所说的:
11.4.6 一元 + 运算符
一元 + 运算符将其操作数转换为数字类型.
产生式 UnaryExpression : + UnaryExpression 的计算如下:
令 expr 成为计算 UnaryExpression 的结果.
Return ToNumber(GetValue(expr)).
ToNumber()
说:
对象
应用以下步骤:
让 primValue 为 ToPrimitive(输入参数,提示字符串).
返回到字符串(primValue).
ToPrimitive()
说:
对象
返回对象的默认值.通过调用对象的 [[DefaultValue]] 内部方法,传递可选的提示 PreferredType 来检索对象的默认值.[[DefaultValue]] 内部方法的行为由本规范为 8.12.8 中的所有原生 ECMAScript 对象定义.
[[DefaultValue]]
说:
8.12.8 [[DefaultValue]](提示)
当使用hint String调用O的[[DefaultValue]]内部方法时,采取如下步骤:
令 toString 为调用对象 O 的 [[Get]] 内部方法的结果,参数为toString".
如果 IsCallable(toString) 为真,则
一个.令 str 为调用 toString 的 [[Call]] 内部方法的结果,O 为 this 值,参数列表为空.
B.如果 str 是原始值,则返回 str.
数组的 .toString
表示:
15.4.4.2 Array.prototype.toString()
调用toString方法时,采取如下步骤:
令数组成为对 this 值调用 ToObject 的结果.
令 func 是调用数组的 [[Get]] 内部方法的结果,参数为join".
如果 IsCallable(func) 为 false,则让 func 为标准内置方法 Object.prototype.toString (15.2.4.2).
返回调用func的[[Call]]内部方法的结果作为this值和空参数列表.
所以 +[]
归结为 +""
,因为 [].join() === ""
.>
同样,+
定义为:
11.4.6 一元 + 运算符
一元 + 运算符将其操作数转换为数字类型.
产生式 UnaryExpression : + UnaryExpression 的计算如下:
令 expr 成为计算 UnaryExpression 的结果.
Return ToNumber(GetValue(expr)).
ToNumber
为 ""
定义为:
StringNumericLiteral ::: [empty] 的 MV 为 0.
所以 +"" === 0
,因此 +[] === 0
.
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:
ToNumber()
says:
ToPrimitive()
says:
[[DefaultValue]]
says:
The .toString
of an array says:
So +[]
comes down to +""
, because [].join() === ""
.
Again, the +
is defined as:
ToNumber
is defined for ""
as:
So +"" === 0
, and thus +[] === 0
.
这篇关于为什么 ++[[]][+[]]+[+[]] 返回字符串“10"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!