在阅读dzone 上发布的这篇文章时,我发现了一段 JavaScript 片段,最初由 Marcus Lagergren 发布在 Twitter 上。
以下代码显然打印了字符串 "fail"
(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];
这涉及隐式类型转换,我试图了解如何准确解释这一行。
我已经隔离了每个角色
(![]+[])[+[]]印刷"f"(![]+[])[+!+[]]印刷"a"([![]]+[][[]])[+!+[]+[+[]]]印刷"i"(![]+[])[!+[]+!+[]]印刷"l"
我还设法分解了返回每个字母的表达式 "i"
信 "f"
![]空数组是一个对象,根据ECMAScript 文档,true当转换为 a 时,点 9.2 的计算结果boolean为false
false+[]根据第 11.6.1 点,二元+运算符的两个参数都被转换为字符串,因此我们得到"false"+"",它计算"false"
+[]如果参数是一个,一元加运算符会导致一个ToNumber转换,然后是一个ToPrimitive转换Object。这种转换的结果是通过调用[[DefaultValue]]对象的内部方法来确定的。如果是空数组,则默认为0。(ECMAScript 文档,章节:11.4.6 , 9.3 , 9.1)
"false"[0]我们正在访问 index 处的字符0,因此"f"
信 "a"
同样的故事,这里唯一的区别是方括号中部分的额外转换(计算结果为一个数字以指向字符串中的另一个字符"false"),由使用一元+和!运算符触发。
+[]评估为0,如上所述。
!0计算true为第 9.2节和第 11.4.9 节中的定义。首先,0转换为布尔值false,然后运算符反转该值。
+true再次,一元加号触发ToNumber转换,返回一个1for binary 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 规则的链接。
我觉得最神秘的是这部分: [][[]]