为什么以及如何([![]] + [] [[]])[+!+ [] + [+ []]]评估为字母"i"?

ton*_*edz 41 javascript obfuscation types ecmascript-5

在阅读dzone上发布的这篇文章时,我发现了一段最初由Marcus Lagergren在Twitter上发布的JavaScript片段.

以下代码显然打印字符串 "fail"

(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];
Run Code Online (Sandbox Code Playgroud)

这涉及隐式类型转换,我试图理解这条线的解释方式.

我已经隔离了每个角色

  • (![]+[])[+[]] 版画 "f"
  • (![]+[])[+!+[]] 版画 "a"
  • ([![]]+[][[]])[+!+[]+[+[]]] 版画 "i"
  • (![]+[])[!+[]+!+[]] 版画 "l"

我还设法打破了每个字母除外的表达式 "i"

信件 "f"

![]空数组是一个对象,它根据ECMAScript的文档,点9.2的计算结果为true当转换为一个boolean,所以这是false

false+[]根据Point 11.6.1,二元+运算符的两个参数都转换为String,因此我们得到"false"+"",它进行求值"false"

+[]如果参数是a,则一元加号运算符会导致ToNumber转换,然后ToPrimitive转换Object.通过调用[[DefaultValue]]对象的内部方法来确定这种转换的结果.如果是空数组,则默认为0.(ECMAScript的文档,章节:11.4.6,9.3,9.1)

"false"[0]我们正在访问索引处的字符0,因此"f"

信件 "a"

同样的故事,这里唯一的区别是方括号中的部分中的额外转换(其计算为指向字符串中另一个字符的数字"false"),由使用一元+!运算符触发.

+[]0如上所述,评估为.

!0评估结果true第9.2 第11.4.9节.首先,0转换为布尔值false,然后运算符反转该值.

+true再一次,一元加号触发ToNumber转换,返回1二进制true (第11.4.69.3 )

"false"[1] 返回字符串中的第二个字符,即 "a"

字母"l"

!+[]评估true如上所述

true+true+在原语上使用二进制触发ToNumber转换.在真实的情况下,其结果是11+1平等2

"false"[2] - 自我解释

信件 "i"

这封信让我感到难过"i".我可以看到第二部分(在方括号中)评估字符串"10",第一部分(在括号中)返回,"falseundefined"我无法对这是如何发生的正面或反面.有人可以一步一步解释吗?特别是方括号发生的魔力?(数组和数组访问)

如果可能的话,我希望每个步骤都包含指向基础ECMAScript规则的链接.

我发现最神秘的是这一部分: [][[]]

Ble*_*der 36

如果你重写一下,你的神秘部分并不是那么神秘:

[]['']
Run Code Online (Sandbox Code Playgroud)

[]将被强制转换为字符串,因为它不是整数,因此您正在寻找[]具有名称''(空字符串)的属性.你会得到的undefined,因为没有这个名字的财产.

至于实际的字母,将表达式分解为两个主要组成部分:

  • 字符串([![]]+[][[]]):
    • [![]][false].
    • [][[]]undefined.
    • 将它们加在一起就可以了"falseundefined".
  • 而指数:[+!+[]+[+[]]].一些空格和括号将使操作更清晰[+(!(+[])) + [+[]]]:
    • [+[]][0].
    • +[]强制[]转换为整数,所以你得到0.
    • !+[]强制0转换为布尔值并否定它,所以你得到了true.
    • +!+[]强制true转换为整数,所以你得到1.
    • 将它们加在一起,就可以了["10"].

当使用字符串访问数组的属性并且字符串碰巧是数组的元素时,字符串被强制转换为整数并且您返回数组的实际元素:

> [1, 2, 3]["0"]
1
> [1, 2, 3]["1"]
2
Run Code Online (Sandbox Code Playgroud)

所以你的最终结果是:

> "falseundefined"["10"]
"i"
Run Code Online (Sandbox Code Playgroud)

阅读此答案以获得该[false] + undefined部件的说明.