在阅读dzone 上发布的这篇文章时,我发现了Marcus Lagergren 在 Twitter 上最初发布的一段 JavaScript 。
以下代码显然打印了字符串"fail"
(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];
这涉及隐式类型转换,我试图了解这一行是如何解释的。
我已经隔离了每个角色
(![]+[])[+[]]
印刷"f"
(![]+[])[+!+[]]
印刷"a"
([![]]+[][[]])[+!+[]+[+[]]]
印刷"i"
(![]+[])[!+[]+!+[]]
印刷"l"
我还设法分解了返回每个字母的表达式,除了"i"
信"f"
![]
一个空数组是一个对象,根据ECMAScript 文档,true
当转换为 a 时,第 9.2 点的计算boolean
结果为false
false+[]
根据第 11.6.1 点,二元+
运算符的两个参数都转换为字符串,因此我们得到"false"+""
,它计算"false"
+[]
如果参数是 ,一元加号运算符会导致ToNumber
转换,然后进行转换。这种转换的结果是通过调用对象的内部方法来确定的。如果是空数组,则默认为. (ECMAScript文档,章节:11.4.6、9.3、9.1)ToPrimitive
Object
[[DefaultValue]]
0
"false"[0]
我们正在访问 index 处的字符0
,因此"f"
信"a"
同样的故事,这里唯一的区别是方括号部分中的附加转换(它计算为一个数字以指向字符串中的另一个字符),由使用一元和运算符"false"
触发。+
!
+[]
评估为0
,如上所述。
!0
评估为第 9.2节和第 11.4.9true
节中定义的值。首先,转换为布尔值,然后运算符反转该值。0
false
+true
再次,一元加触发ToNumber
转换,它返回一个1
二进制true
(第 11.4.6和9.3节)
"false"[1]
返回字符串中的第二个字符,即"a"
字母“l”
!+[]
评估true
为如上所述
true+true
在原语上使用二进制+
会触发ToNumber
转换。如果为真,则其结果为1
且1+1
等于2
"false"[2]
- 自我解释
信"i"
让我难过的是这封信"i"
。我可以看到第二部分(在方括号中)计算为字符串"10"
,并且第一部分(在括号中)返回"falseundefined"
,但我无法确定这是如何发生的。有人可以逐步解释吗?尤其是方括号的神奇之处?(数组和数组访问)
如果可能的话,我希望每个步骤都包含一个指向底层 ECMAScript 规则的链接。
我觉得最神秘的是这部分:[][[]]