为什么以及(] + ]) + ]]的计算结果为字母“i”?
在阅读这篇贴在dzone上的文章时,我发现了由Marcus Lagergren最初在Twitter上发布的一段JavaScript代码。
下面的代码显然打印string"fail"
(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];
这涉及到隐式types转换,我试图理解这条线是如何解释的。
我已经隔离每个字符
-
(![]+[])[+[]]打印"f" -
(![]+[])[+!+[]]打印"a" -
([![]]+[][[]])[+!+[]+[+[]]]打印"i" -
(![]+[])[!+[]+!+[]]打印"l"
我也设法分解expression式,从"i"
字母"f"
![]一个空数组是一个对象,根据ECMAScript文档,点9.2在转换为boolean时计算为true ,所以这是false
false+[]按照第11.6.1节二进制+运算符的两个参数都被转换为String,因此我们得到"false"+"" ,其结果为"false"
+[]一个加号运算符会导致一个ToNumber转换,如果该参数是一个Object则会进行ToPrimitive转换。 这种转换的结果是通过调用对象的[[DefaultValue]]内部方法来确定的。 如果数组为空,则默认为0 。 (ECMAScript文档,章节: 11.4.6,9.3,9.1 )
"false"[0]我们访问索引为0的字符,因此"f"
字母"a"
同样的故事,这里唯一的区别是方括号内的部分(通过使用一元+和! )触发的额外的转换(通过计算一个数字来指向string"false"中的另一个字符) ! 运营商。
如上所述, +[]计算结果为0 。
如第9.2 节和第11.4.9 节中定义的那样, !0评估为true 。 首先,将0转换为布尔值false ,然后运算符将该值反转。
+true再次为+true ,一元正则触发一个ToNumber转换,它返回一个1表示二进制true ( Section 11.4.6 and 9.3 )
"false"[1]返回string中的第二个字符,即"a"
字母“l”
!+[]计算结果如上所述
使用基元上的二进制+ true+true触发ToNumber转换。 如果是,则结果是1+1等于2
"false"[2] – 自我解释
字母"i"
让我难过的是字母"i" 。 我可以看到第二部分(在方括号内)的计算结果为string"10" ,第一部分(在括号内)返回"falseundefined"但是我不能对这种情况做出 "falseundefined" 或 "falseundefined" 。 有人可以一步一步解释吗? 特别是用方括号发生的魔法? (数组和数组访问)
如果可能,我希望每一步都包含一个指向底层ECMAScript规则的链接。
我觉得最神秘的是这部分: [][[]]
如果你稍微改写一下,你的神秘部分并不是那么神秘:
[]['']
[]将被强制为一个string,因为它不是一个整数,所以你正在寻找名称为'' (一个空string)的[]属性。 你会得到undefined ,因为没有这个名字的财产。
至于实际的信件,把expression分成两个主要部分:
- string
([![]]+[][[]]):-
[![]]是[false]。 -
[][[]]undefined。 - 将它们加在一起,就会得到
"falseundefined"。
-
- 和索引:
[+!+[]+[+[]]]。 一些空格和括号会使操作更清晰:[+(!(+[])) + [+[]]]:-
[+[]]是[0]。 -
+[]强制[]为一个整数,所以你得到0。 -
!+[]0强制为一个布尔值,否定它,这样你就可以了。 -
+!+[]强制为一个整数,所以你得到1。 - 把它们加在一起,就会得到
["10"]。
-
使用string访问数组的属性时,string碰巧是数组的一个元素,string被强制为一个整数,并返回数组的实际元素:
> [1, 2, 3]["0"] 1 > [1, 2, 3]["1"] 2
所以你的最终结果是:
> "falseundefined"["10"] "i"
阅读这个答案 ,解释[false] + undefined部分。
([![]]+[][[]])[+!+[]+[+[]]]有两部分:
([![]]+[][[]])和其他你发现自己。
![]返回false 。 然后我们使用获取.toString()行为。 ( []+[]与[].toString()+[].toString()相同[][[]]是未定义的,因为我们试图访问index [] (或[].toString() ,这是未定义的[] 。
对不起以前的回答,我完全误解了你的评论。