在阅读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)ToPrimitiveObject[[DefaultValue]]0
"false"[0]我们正在访问 index 处的字符0,因此"f"
信"a"
同样的故事,这里唯一的区别是方括号部分中的附加转换(它计算为一个数字以指向字符串中的另一个字符),由使用一元和运算符"false"触发。+!
+[]评估为0,如上所述。
!0评估为第 9.2节和第 11.4.9true节中定义的值。首先,转换为布尔值,然后运算符反转该值。0false
+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 规则的链接。
我觉得最神秘的是这部分:[][[]]