【发布时间】:2013-06-05 13:42:15
【问题描述】:
在阅读 this article posted on dzone 时,我发现了一个 JavaScript 的 sn-p,最初是 posted on Twitter by Marcus Lagergren。
以下代码显然打印了字符串"fail"
(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];
这涉及隐式类型转换,我试图了解如何准确地解释这一行。
我已经隔离了每个角色
-
(![]+[])[+[]]打印"f" -
(![]+[])[+!+[]]打印"a" -
([![]]+[][[]])[+!+[]+[+[]]]打印"i" -
(![]+[])[!+[]+!+[]]打印"l"
除了"i"之外,我还设法分解了返回每个字母的表达式
信"f"
![] 一个空数组是一个对象,根据ECMAScript documentation, point 9.2,它在转换为boolean 时计算为true,所以这是false
false+[] 根据Point 11.6.1 二进制+ 运算符的两个参数都转换为字符串,因此我们得到"false"+"",它评估"false"
+[] 一元加号运算符会导致ToNumber 转换,如果参数是Object,则后跟ToPrimitive 转换。这种转换的结果是通过调用对象的[[DefaultValue]] 内部方法来确定的。如果是空数组,则默认为0。
(ECMAScript 文档,章节:11.4.6、9.3、9.1)
"false"[0] 我们正在访问索引0 处的字符,因此"f"
信"a"
同样的故事,这里唯一的区别是方括号中的部分的额外转换(其计算结果为指向字符串 "false" 中的另一个字符的数字),由使用一元 + 和 @987654365 触发@ 运算符。
+[] 计算结果为 0,如上所述。
!0 的计算结果为 true,如 Section 9.2 和 Section 11.4.9 中所定义。首先,0 转换为布尔值false,然后运算符将值取反。
+true 再次,一元加号触发ToNumber 转换,它为二进制true 返回一个1
(Section 11.4.6 和 9.3)
"false"[1] 返回字符串中的第二个字符,即"a"
字母“l”
!+[] 计算结果为 true,如上所述
true+true 在原语上使用二进制 + 会触发 ToNumber 转换。如果为真,其结果为1 和1+1 等于2
"false"[2] - 不言自明
信"i"
让我难过的是"i"这封信。我可以看到第二部分(在方括号中)计算为字符串"10",第一部分(在括号中)返回"falseundefined",但我无法确定这是如何发生的。有人可以一步一步解释吗?尤其是方括号的神奇之处? (数组和数组访问)
如果可能,我希望每个步骤都包含指向基础 ECMAScript 规则的链接。
我觉得最神秘的是这部分:[][[]]
【问题讨论】:
-
@thg435 谢谢,我正在阅读这篇文章。虽然它看起来更像是这样的酷表情的集合。我希望看到有关此特定案例的标准参考的完整解释。
-
这已经被问过了。
标签: javascript types obfuscation ecmascript-5