首页 > 代码库 > 啥? ++[[]][+[]]+[+[]] = 10?
啥? ++[[]][+[]]+[+[]] = 10?
咱先把这个表达式分开:
++[[]][+[]]
+
[+[]]
在JavaScript中, 下面等式是true +[]===0
. +
会把一些字符转换成数字, 在这里它会变成 +""
or 0
(详细规则如下).
咱可以把它简化成这样 (++
的优先级比 +
更高):
++[[]][0]
+
[0]
因此 [[]][0]
意味着: 获取 [[]]
的第一个元素,实际上:
[[]][0]
返回内部的数组 ([]
). 根据语言规范,说[[]][0]===[]
是不对的,咱把内部这个数组称为A
以免误会.++[[]][0]==A+1
, 因为++
意味着 ‘加1‘.++[[]][0]===+(A+1)
; 换句话说,这玩意儿得到的永远是个数值 (+1
不一定返回一个数值, 但++
一定是).
咱可以让表达式更简化. 用 []
替换 A
:
+([] + 1)
+
[0]
在JavaScript中, 这个等式也是true: []+1==="1"
, 因为[]==""
(连接一个空数组), so:
+([]+1)===+(""+1)
, and+(""+1)===+("1")
, and+("1")===1
还可以更简化:
1
+
[0]
在 JavaScript中这个等式 [0]=="0"
, 也是true,因为这相当于一个 有一个元素的数组内部元素的连接。连接各元素使用 ,
分割,当只有一个元素时,可以推出结果就是这个元素本身。
故此, 我们最终得出 (number + string = string):
1
+
"0"
==="10" // 耶!
+[]
的详细规则如下:
对于 +[]
, 首先会被转化成一个 string 因为这是 +
规定的:
11.4.6 一元运算符 +
+ 运算符会把操作数转化成 Number 类型.
下面这个一元表达式 : + 一元表达式 会进行如下操作:
令 expr 为一元表达式的结果.
返回 ToNumber(GetValue(expr)).
ToNumber()
:
Object
应用如下步骤:
令 primValue 为 ToPrimitive(input argument, hint String).
返回 ToString(primValue).
ToPrimitive()
:
Object
返回这个Object的默认值。默认值咋算呢,通过调用 [[DefaultValue]] 这个 object的内部方法, passing the optional hint PreferredType. [[DefaultValue]] 方法定义见 ECMAScript objects 中 8.12.8.
[[DefaultValue]]
:
8.12.8 [[DefaultValue]] (hint)
当object O内部方法 [[DefaultValue]] 被调用时, 会执行如下操作: (不翻译了,各位自己感兴趣的话自己看吧)
Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".
If IsCallable(toString) is true then,
a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
b. If str is a primitive value, return str.
The .toString
of an array says:
15.4.4.2 Array.prototype.toString ( )
When the toString method is called, the following steps are taken:
Let array be the result of calling ToObject on the this value.
Let func be the result of calling the [[Get]] internal method of array with argument "join".
If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).
Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.
So +[]
comes down to +""
, because [].join()===""
.
Again, the +
is defined as:
11.4.6 Unary + Operator
The unary + operator converts its operand to Number type.
The production UnaryExpression : + UnaryExpression is evaluated as follows:
Let expr be the result of evaluating UnaryExpression.
Return ToNumber(GetValue(expr)).
ToNumber
is defined for ""
as:
The MV of StringNumericLiteral ::: [empty] is 0.
So +""===0
, and thus +[]===0
.
啥? ++[[]][+[]]+[+[]] = 10?