"10"这是有效的,并返回JavaScript中的字符串:
"10"
console.log(++[[]][+[]]+[+[]])
为什么?这里发生了什么?
如果我们将其拆分,则混乱等于:
++[[]][+[]] + [+[]]
在 JavaScript 中,确实如此+[] === 0。+将某物转换为数字,在这种情况下,它将归结为+""或0(请参阅下面的规范详细信息)。
+[] === 0
+
+""
0
因此,我们可以简化它(++优先于+):
++
++[[]][0] + [0]
因为[[]][0]意味着:从 中获取第一个元素[[]],所以确实:
[[]][0]
[[]]
[[]][0]返回内部数组 ( [])。由于引用,说 是错误的[[]][0] === [],但让我们调用内部数组A以避免错误的表示法。
[]
[[]][0] === []
A
++在其操作数之前表示“递增一并返回递增的结果”。所以++[[]][0]等价于Number(A) + 1(或+A + 1)。
++[[]][0]
Number(A) + 1
+A + 1
同样,我们可以将混乱简化为更清晰的内容。让我们[]换回A:
(+[] + 1) + [0]
在+[]将数组强制转换为 number之前0,需要先将其强制转换为字符串,即"", 再次。最后,1添加 ,结果为1。
+[]
""
1
(+[] + 1) === (+"" + 1)
(+"" + 1) === (0 + 1)
(0 + 1) === 1
让我们进一步简化它:
1 + [0]
此外,在 JavaScript: 中也是如此[0] == "0",因为它使用一个元素连接数组。加入将连接由 分隔的元素,。使用一个元素,您可以推断此逻辑将导致第一个元素本身。
[0] == "0"
,
在这种情况下,+看到两个操作数:一个数字和一个数组。它现在正试图将两者强制为同一类型。首先,将数组强制转换为字符串"0",然后将数字强制转换为字符串 ( "1")。数字+字符串===字符串。
"0"
"1"
===
"1" + "0" === "10" // Yay!
规格详细信息+[]:
这是一个迷宫,但要做到这一点+[],首先它被转换为字符串,因为这+就是说:
11.4.6 一元+运算符 一元 + 运算符将其操作数转换为 Number 类型。 产生式 UnaryExpression : + UnaryExpression 的评估如下: 令 expr 为计算 UnaryExpression 的结果。 返回 ToNumber(GetValue(expr))。
11.4.6 一元+运算符
一元 + 运算符将其操作数转换为 Number 类型。
产生式 UnaryExpression : + UnaryExpression 的评估如下:
ToNumber()说:
ToNumber()
目的 应用以下步骤: 设 primValue 为 ToPrimitive(输入参数,提示字符串)。 返回 ToString(primValue)。
目的
应用以下步骤:
ToPrimitive()说:
ToPrimitive()
目的 返回对象的默认值。通过调用对象的 [[DefaultValue]] 内部方法检索对象的默认值,并传递可选提示 PreferredType。本规范为 8.12.8 中的所有原生 ECMAScript 对象定义了 [[DefaultValue]] 内部方法的行为。
返回对象的默认值。通过调用对象的 [[DefaultValue]] 内部方法检索对象的默认值,并传递可选提示 PreferredType。本规范为 8.12.8 中的所有原生 ECMAScript 对象定义了 [[DefaultValue]] 内部方法的行为。
[[DefaultValue]]说:
[[DefaultValue]]
8.12.8 [[DefaultValue]](提示) 当使用提示String调用O的[[DefaultValue]]内部方法时,采取以下步骤: 令 toString 为使用参数“toString”调用对象 O 的 [[Get]] 内部方法的结果。 如果 IsCallable(toString) 为真,则 一个。令 str 为调用 toString 的 [[Call]] 内部方法的结果,其中 O 作为 this 值和一个空参数列表。 湾。如果 str 是原始值,则返回 str。
8.12.8 [[DefaultValue]](提示)
当使用提示String调用O的[[DefaultValue]]内部方法时,采取以下步骤:
一个。令 str 为调用 toString 的 [[Call]] 内部方法的结果,其中 O 作为 this 值和一个空参数列表。
湾。如果 str 是原始值,则返回 str。
.toString数组的 说:
.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 值和一个空参数列表。
15.4.4.2 Array.prototype.toString()
当调用 toString 方法时,会执行以下步骤:
所以+[]归结为+"",因为[].join() === ""。
[].join() === ""
同样,+定义为:
ToNumber定义为"":
ToNumber
StringNumericLiteral ::: [empty] 的 MV 为 0。
如此+"" === 0,如此,如此+[] === 0。
+"" === 0