一尘不染

为什么++ [[]] [+ []] + [+ []]返回字符串“ 10”?

javascript

这是有效的,并返回"10"JavaScript中的字符串

console.log(++[[]][+[]]+[+[]])

为什么?这是怎么回事


阅读 253

收藏
2020-04-25

共1个答案

一尘不染

如果我们将其拆分,则混乱等于:

++[[]][+[]]
+
[+[]]

在JavaScript中,确实是这样+[]===0+将某物转换为数字,在这种情况下,它将降为+""0(请参见下面的规范详细信息)。

因此,我们可以简化它(++优先于+):

++[[]][0]
+
[0]

因为[[]][0]意思是:从中获取第一个元素[[]],所以确实:

[[]][0]返回内部数组([])。由于引用,说错了[[]][0]===[],但是让我们调用内部数组A以避免错误的表示法。
++在其操作数之前表示“加1并返回加结果”。因此++[[]][0]等于Number(A) + 1(或+A + 1)。

同样,我们可以将混乱简化为更清晰的内容。让我们替换[]A

(+[] + 1)
+
[0]

+[]将数组强制转换为number之前0,需要先将其强制转换为字符串,即""再次。最后1添加,结果为1

  • (+[] + 1) === (+"" + 1)
  • (+"" + 1) === (0 + 1)
  • (0 + 1) === 1

让我们进一步简化一下:

1
+
[0]

同样,在JavaScript:中也是如此[0]=="0",因为它是将一个元素与一个数组连接在一起。连接将连接由分隔的元素,。使用一个元素,您可以推断出此逻辑将导致第一个元素本身。

在这种情况下,+将看到两个操作数:一个数字和一个数组。现在,它试图将两者强制转换为同一类型。首先,将数组强制转换为字符串"0",然后将数字强制转换为字符串("1")。
Number+字符串===String

"1" + "0" === "10" // Yay!

规格详细信息+[]

+[]真是一个迷宫,但要做到这一点,首先要将其转换为字符串,因为这是这样+说的:

11.4.6一元+运算符

一元+运算符将其操作数转换为Number类型。

产生UnaryExpression:+ UnaryExpression的评估如下:

  1. 令expr为评估UnaryExpression的结果。

  2. 返回ToNumber(GetValue(expr))。

ToNumber() 说:

宾语

应用以下步骤:

  1. 令primValue为ToPrimitive(输入参数,提示字符串)。

  2. 返回ToString(primValue)。

ToPrimitive() 说:

宾语

返回对象的默认值。通过调用对象的[[DefaultValue]]内部方法并传递可选提示PreferredType来检索对象的默认值。本规范为8.12.8中的所有本机ECMAScript对象定义了[[DefaultValue]]内部方法的行为。

[[DefaultValue]] 说:

8.12.8 [[DefaultValue]](提示)

使用提示字符串调用O的[[DefaultValue]]内部方法时,将执行以下步骤:

  1. 令toString为使用参数“ toString”调用对象O的[[Get]]内部方法的结果。

  2. 如果IsCallable(toString)为true,

一个。令str为调用toString的[[Call]]内部方法的结果,其中O为this值,并且参数列表为空。

b。如果str是原始值,则返回str。

.toString数组的说:

15.4.4.2 Array.prototype.toString()

调用toString方法时,将执行以下步骤:

  1. 令array为在this值上调用ToObject的结果。

  2. 令func为使用参数“ join”调用array的[[Get]]内部方法的结果。

3.
如果IsCallable(func)为false,则将func设为标准的内置方法Object.prototype.toString(15.2.4.2)。

  1. 返回调用func提供数组的[[Call]]内部方法的结果作为this值和空参数列表。

所以+[]归结为+"",因为[].join() === ""

同样,+定义为:

11.4.6一元+运算符

一元+运算符将其操作数转换为Number类型。

产生UnaryExpression:+ UnaryExpression的评估如下:

  1. 令expr为评估UnaryExpression的结果。

  2. 返回ToNumber(GetValue(expr))。

ToNumber被定义为""

StringNumericLiteral ::: [空]的MV为0。

如此+"" === 0,如此+[] === 0

2020-04-25