这是有效的,并在JavaScript中返回字符串“10”(此处有更多示例):
控制台日志(++[[]][+[]]+[+[]])
为什么?这里发生了什么?
这是有效的,并在JavaScript中返回字符串“10”(此处有更多示例):
控制台日志(++[[]][+[]]+[+[]])
为什么?这里发生了什么?
当前回答
如果我们将其拆分,那么混乱就等于:
++[[]][+[]]
+
[+[]]
在JavaScript中,+[]===0.+将某物转换为数字,在这种情况下,它将降为+“”或0(请参阅下面的规范详细信息)。
因此,我们可以简化它(++优先于+):
++[[]][0]
+
[0]
因为[[]][0]的意思是:从[[]]中获取第一个元素,所以:
[[]][0]返回内部数组([])。由于引用,说[[]][0]==[]是错误的,但让我们调用内部数组A以避免错误的表示法。
++在其操作数之前表示“递增一并返回递增的结果”。因此,++[[]][0]等同于数字(A)+1(或+A+1)。
同样,我们可以将混乱简化为更清晰的内容。让我们用[]代替A:
(+[] + 1)
+
[0]
在+[]可以将数组强制为数字0之前,需要先将其强制为字符串,也就是“”。最后,添加1,得到1。
(+[] + 1) === (+"" + 1)(+"" + 1) === (0 + 1)(0 + 1) === 1
让我们更加简化:
1
+
[0]
同样,JavaScript中也是如此:[0]==“0”,因为它是用一个元素连接数组。连接将连接由、分隔的元素,。通过一个元素,您可以推断出这个逻辑将导致第一个元素本身。
在这种情况下,+看到两个操作数:一个数字和一个数组。现在,它正试图将两者强制为同一类型。首先,数组被强制转换为字符串“0”,然后,数字被强制转换成字符串(“1”)。数字+字符串==字符串。
"1" + "0" === "10" // Yay!
+[]的详细规范:
这是一个相当复杂的问题,但要做到+[],首先要将其转换为字符串,因为这就是+所说的:
11.4.6一元+运算符一元+运算符将其操作数转换为Number类型。生产UnaryExpression:+UnaryExpression的计算如下:让expr是对UnaryExpression求值的结果。返回到编号(GetValue(expr))。
ToNumber()表示:
对象应用以下步骤:让primValue为ToPrimitive(输入参数,提示字符串)。返回到字符串(primValue)。
ToPrimitive()表示:
对象返回对象的默认值。通过调用对象的[[DefaultValue]]内部方法并传递可选提示PreferredType来检索对象的默认值。[[DefaultValue]]内部方法的行为由8.12.8中所有本机ECMAScript对象的规范定义。
[[DefaultValue]]表示:
8.12.8[[DefaultValue]](提示)当使用提示字符串调用O的[[DefaultValue]]内部方法时,将采取以下步骤:让toString是用参数“toString”调用对象O的[[Get]]内部方法的结果。如果IsCallable(toString)为真,a.让str是调用toString的[[Call]]内部方法的结果,此值为O,参数列表为空。b.如果str是基元值,则返回str。
数组的.toString表示:
15.4.4.2阵列.原型.字符串()调用toString方法时,将执行以下步骤:让数组是对该值调用ToObject的结果。让func是用参数“join”调用数组的[[Get]]内部方法的结果。如果IsCallable(func)为false,则让func为标准内置方法Object.prototype.toString(15.2.4.2)。返回调用func提供数组的[[Call]]内部方法的结果,作为this值和空参数列表。
所以+[]归结为+“”,因为[].jjoin()==“”。
同样,+定义为:
11.4.6一元+运算符一元+运算符将其操作数转换为Number类型。生产UnaryExpression:+UnaryExpression的计算如下:让expr是对UnaryExpression求值的结果。返回到编号(GetValue(expr))。
“”的ToNumber定义为:
StringNumericLiteral:::[empty]的MV为0。
因此+“”===0,因此+[]===0。
其他回答
一步一步,+将值转换为数字,如果您添加到空数组+[]。。。因为它是空的并且等于0,所以它将
从那里开始,现在看看你的代码,它是++[[]][+[]]+[+[]]。。。
它们之间有一个加号++[]][+[]]+[+[]]
因此,这些[+[]]将返回[0],因为它们有一个空数组,在另一个数组中转换为0。。。
如图所示,第一个值是一个二维数组,其中有一个数组。。。因此[[]][+[]]将等于[[]][0],后者将返回[]。。。
最后++将其转换为1。。。
所以你可以想象,1+“0”将是“10”。。。
+[]计算结果为0[…]然后将其与任何东西相加(+运算),将数组内容转换为由逗号连接的元素组成的字符串表示。
任何其他的东西,比如数组的索引(比+操作的优先级更高)都是有序的,没有什么有趣的。
++[[]][+[]]+[+[]]
^^^
|
v
++[[]][+[]]+[0]
^^^
|
v
++[[]][0]+[0]
^^^^^^^
|
v
++[]+[0]
^^^
|
v
++[]+"0"
^^^^
|
v
++0+"0"
^^^
|
v
1+"0"
^^^^^
|
v
"10"
+运算符通过.valueOf()强制任何非数字操作数。如果不返回数字,则调用.toString()。
我们可以通过以下方式进行验证:
常量x=[],y=[];x.valueOf=()=>(console.log('x.valueOf()已被调用'),y.valueOf));x.toString=()=>(console.log('x.toString()已被调用'),y.toString(());console.log(`+x->${+x}`);
所以+[]与将“”强制为0相同。
如果任何操作数是字符串,则+连接。
++[ [] ][+[]] === 1+[] === 0++[ [] ][0] === 1[+[]]是[0]
然后我们有一个字符串连接:
1+字符串([0])==10
如果我们将其拆分,那么混乱就等于:
++[[]][+[]]
+
[+[]]
在JavaScript中,+[]===0.+将某物转换为数字,在这种情况下,它将降为+“”或0(请参阅下面的规范详细信息)。
因此,我们可以简化它(++优先于+):
++[[]][0]
+
[0]
因为[[]][0]的意思是:从[[]]中获取第一个元素,所以:
[[]][0]返回内部数组([])。由于引用,说[[]][0]==[]是错误的,但让我们调用内部数组A以避免错误的表示法。
++在其操作数之前表示“递增一并返回递增的结果”。因此,++[[]][0]等同于数字(A)+1(或+A+1)。
同样,我们可以将混乱简化为更清晰的内容。让我们用[]代替A:
(+[] + 1)
+
[0]
在+[]可以将数组强制为数字0之前,需要先将其强制为字符串,也就是“”。最后,添加1,得到1。
(+[] + 1) === (+"" + 1)(+"" + 1) === (0 + 1)(0 + 1) === 1
让我们更加简化:
1
+
[0]
同样,JavaScript中也是如此:[0]==“0”,因为它是用一个元素连接数组。连接将连接由、分隔的元素,。通过一个元素,您可以推断出这个逻辑将导致第一个元素本身。
在这种情况下,+看到两个操作数:一个数字和一个数组。现在,它正试图将两者强制为同一类型。首先,数组被强制转换为字符串“0”,然后,数字被强制转换成字符串(“1”)。数字+字符串==字符串。
"1" + "0" === "10" // Yay!
+[]的详细规范:
这是一个相当复杂的问题,但要做到+[],首先要将其转换为字符串,因为这就是+所说的:
11.4.6一元+运算符一元+运算符将其操作数转换为Number类型。生产UnaryExpression:+UnaryExpression的计算如下:让expr是对UnaryExpression求值的结果。返回到编号(GetValue(expr))。
ToNumber()表示:
对象应用以下步骤:让primValue为ToPrimitive(输入参数,提示字符串)。返回到字符串(primValue)。
ToPrimitive()表示:
对象返回对象的默认值。通过调用对象的[[DefaultValue]]内部方法并传递可选提示PreferredType来检索对象的默认值。[[DefaultValue]]内部方法的行为由8.12.8中所有本机ECMAScript对象的规范定义。
[[DefaultValue]]表示:
8.12.8[[DefaultValue]](提示)当使用提示字符串调用O的[[DefaultValue]]内部方法时,将采取以下步骤:让toString是用参数“toString”调用对象O的[[Get]]内部方法的结果。如果IsCallable(toString)为真,a.让str是调用toString的[[Call]]内部方法的结果,此值为O,参数列表为空。b.如果str是基元值,则返回str。
数组的.toString表示:
15.4.4.2阵列.原型.字符串()调用toString方法时,将执行以下步骤:让数组是对该值调用ToObject的结果。让func是用参数“join”调用数组的[[Get]]内部方法的结果。如果IsCallable(func)为false,则让func为标准内置方法Object.prototype.toString(15.2.4.2)。返回调用func提供数组的[[Call]]内部方法的结果,作为this值和空参数列表。
所以+[]归结为+“”,因为[].jjoin()==“”。
同样,+定义为:
11.4.6一元+运算符一元+运算符将其操作数转换为Number类型。生产UnaryExpression:+UnaryExpression的计算如下:让expr是对UnaryExpression求值的结果。返回到编号(GetValue(expr))。
“”的ToNumber定义为:
StringNumericLiteral:::[empty]的MV为0。
因此+“”===0,因此+[]===0。