如果我们把它分开,混乱程度等于:
++[[]][+[]]
+
[+[]]
在 JavaScript 中,确实如此+[] === 0
. +
将某些内容转换为数字,在本例中它将归结为+""
or 0
(请参阅下面的规格详细信息)。
因此,我们可以简化它(++
优先于+
):
++[[]][0]
+
[0]
Because [[]][0]
意思是:获取第一个元素[[]]
,确实如此:
[[]][0]
返回内部数组 ([]
)。由于参考文献的说法是错误的[[]][0] === []
,但我们称内部数组为A
以避免错误的符号。
++
其操作数前面的意思是“加一并返回增加后的结果”。所以++[[]][0]
相当于Number(A) + 1
(or +A + 1
).
同样,我们可以将混乱简化为更清晰的内容。我们来代替[]
回来为A
:
(+[] + 1)
+
[0]
Before +[]
可以将数组强制转换为数字0
,需要先强制转换为字符串,即""
, 再次。最后,1
添加,结果是1
.
(+[] + 1) === (+"" + 1)
(+"" + 1) === (0 + 1)
(0 + 1) === 1
让我们进一步简化它:
1
+
[0]
另外,在 JavaScript 中也是如此:[0] == "0"
,因为它将一个数组与一个元素连接起来。连接将连接由 分隔的元素,
。对于一个元素,您可以推断出该逻辑将产生第一个元素本身。
在这种情况下,+
看到两个操作数:一个数字和一个数组。现在它正试图将两者强制为同一类型。首先,将数组强制转换为字符串"0"
,接下来,数字被强制转换为字符串("1"
). Number +
String ===
String.
"1" + "0" === "10" // Yay!
规格详情+[]
:
这是一个迷宫,但是要做+[]
,首先它被转换为字符串,因为这就是+
says:
11.4.6 一元+运算符
一元 + 运算符将其操作数转换为 Number 类型。
产生式 UnaryExpression : + UnaryExpression 的计算如下:
令 expr 为 UnaryExpression 的计算结果。
返回 ToNumber(GetValue(expr))。
ToNumber()
says:
Object
应用以下步骤:
令 primValue 为 ToPrimitive(输入参数,提示字符串)。
返回 ToString(primValue)。
ToPrimitive()
says:
Object
返回对象的默认值。对象的默认值是通过调用对象的 [[DefaultValue]] 内部方法并传递可选提示 PreferredType 来检索的。本规范为 8.12.8 中的所有本机 ECMAScript 对象定义了 [[DefaultValue]] 内部方法的行为。
[[DefaultValue]]
says:
8.12.8 [[默认值]](提示)
当使用提示字符串调用 O 的 [[DefaultValue]] 内部方法时,将执行以下步骤:
令 toString 为使用参数“toString”调用对象 O 的 [[Get]] 内部方法的结果。
如果 IsCallable(toString) 为 true 那么,
A。令 str 为调用 toString 的 [[Call]] 内部方法的结果,其中 O 作为 this 值和一个空参数列表。
b.如果 str 是原始值,则返回 str。
The .toString
数组 说:
15.4.4.2 Array.prototype.toString()
当调用toString方法时,会执行以下步骤:
令 array 为对 this 值调用 ToObject 的结果。
令 func 为使用参数“join”调用数组的 [[Get]] 内部方法的结果。
如果 IsCallable(func) 为 false,则令 func 为标准内置方法 Object.prototype.toString (15.2.4.2)。
返回调用 func 的 [[Call]] 内部方法的结果,提供数组作为 this 值和一个空参数列表。
So +[]
归结为+""
, 因为[].join() === ""
.
再次,+
定义为:
11.4.6 一元+运算符
一元 + 运算符将其操作数转换为 Number 类型。
产生式 UnaryExpression : + UnaryExpression 的计算如下:
令 expr 为 UnaryExpression 的计算结果。
返回 ToNumber(GetValue(expr))。
ToNumber
定义为""
as:
StringNumericLiteral ::: [empty] 的 MV 为 0。
So +"" === 0
, 因此+[] === 0
.