【问题标题】:Why and how does ([![]]+[][[]])[+!+[]+[+[]]] evaluate to the letter "i"? [duplicate]([![]]+[][[]])[+!+[]+[+[]]] 为什么以及如何计算为字母“i”? [复制]
【发布时间】: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.69.39.1

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

"a"

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

+[] 计算结果为 0,如上所述。

!0 的计算结果为 true,如 Section 9.2Section 11.4.9 中所定义。首先,0 转换为布尔值false,然后运算符将值取反。

+true 再次,一元加号触发ToNumber 转换,它为二进制true 返回一个1Section 11.4.69.3

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

字母“l”

!+[] 计算结果为 true,如上所述

true+true 在原语上使用二进制 + 会触发 ToNumber 转换。如果为真,其结果为11+1 等于2

"false"[2] - 不言自明

"i"

让我难过的是"i"这封信。我可以看到第二部分(在方括号中)计算为字符串"10",第一部分(在括号中)返回"falseundefined",但我无法确定这是如何发生的。有人可以一步一步解释吗?尤其是方括号的神奇之处? (数组和数组访问)

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

我觉得最神秘的是这部分:[][[]]

【问题讨论】:

  • @thg435 谢谢,我正在阅读这篇文章。虽然它看起来更像是这样的酷表情的集合。我希望看到有关此特定案例的标准参考的完整解释。
  • 这已经被问过了。

标签: javascript types obfuscation ecmascript-5


【解决方案1】:

([![]]+[][[]])[+!+[]+[+[]]] 有两个部分:

([![]]+[][[]]) 和你自己找到的另一个。

![] 返回false。然后我们使用[...] 得到+.toString() 行为。 ([]+[][].toString()+[].toString() 相同) [][[]] 未定义,因为我们试图访问未定义的 [] 的索引 [](或 [].toString(),即 '')。

抱歉之前的回答,我完全误读了您的评论。

【讨论】:

    【解决方案2】:

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

    []['']
    

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

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

    • 字符串([![]]+[][[]])
      • [![]][false]
      • [][[]]undefined
      • 将它们加在一起,您将得到 "falseundefined"
    • 还有索引:[+!+[]+[+[]]]。一些空格和括号将使操作更加清晰:[+(!(+[])) + [+[]]]
      • [+[]][0]
      • +[][] 强制转换为整数,因此您得到 0
      • !+[]0 强制转换为布尔值并将其取反,因此您得到 true
      • +!+[]true 强制转换为整数,因此您得到 1
      • 将它们加在一起,您会得到["10"]

    当使用字符串访问数组的属性,而字符串恰好是数组的一个元素时,字符串被强制转换为整数,然后你取回数组的实际元素:

    > [1, 2, 3]["0"]
    1
    > [1, 2, 3]["1"]
    2
    

    所以你的最终结果是:

    > "falseundefined"["10"]
    "i"
    

    阅读this answer 了解[false] + undefined 部分的说明。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-06
      • 2012-12-12
      • 2011-10-06
      • 2013-11-10
      • 2013-07-17
      • 2013-03-24
      • 1970-01-01
      • 2011-08-02
      相关资源
      最近更新 更多