首页 文章

为什么以及如何([![]] [] [[]])[! [] [[]]]评价字母“i”? [重复]

提问于
浏览
38

这个问题在这里已有答案:

在阅读this article posted on dzone时,我发现了一段JavaScript,最初是posted on Twitter by Marcus Lagergren .

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

(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];

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

我已经隔离了每个角色

  • (![]+[])[+[]] 打印 "f"

  • (![]+[])[+!+[]] 打印 "a"

  • ([![]]+[][[]])[+!+[]+[+[]]] 打印 "i"

  • (![]+[])[!+[]+!+[]] 打印 "l"

我还成功地将每个字母的表达式分解为 "i"

字母“f”

![] 一个空数组是一个Object,根据ECMAScript documentation, point 9.2在转换为 boolean 时求值为 true 所以这是 false

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

+[] 如果参数为 Object ,则一元加号运算符会导致 ToNumber 转换,然后进行 ToPrimitive 转换 . 通过调用对象的 [[DefaultValue]] internal方法来确定此类转换的结果 . 如果是空数组,则默认为 0 . (ECMAScript文档,部分:11.4.69.39.1

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

字母“a”

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

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

!0 根据Section 9.2Section 11.4.9中的定义求值为 true . 首先,将 0 转换为布尔值 false ,然后运算符将该值反转 .

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

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

字母“l”

如上所述, !+[] 评估为 true

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

"false"[2] - 自我解释

字母“我”

令我难过的是字母 "i" . 我可以看到第二部分(在方括号中)计算字符串 "10" 并且第一部分(在括号中)返回 "falseundefined" 但是 I can't make heads or tails of how this is happening. Could someone explain it step by step? 特别是方括号中出现的魔法? (数组和数组访问)

If possible, I'd like each step to contain a link to the underlying ECMAScript rules.

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

2 回答

  • 36

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

    []['']
    

    [] 将被强制转换为字符串,因为它没有't an integer, so you'正在查找名称为 '' (空字符串)的 [] 属性 . 您将获得 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 部分的说明 .

  • 1

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

    ([![]]+[][[]]) 和你发现的另一个 .

    ![] 返回 false . 然后我们使用 [...] 来获取 +.toString() 行为 . ( []+[][].toString()+[].toString() 相同) [][[]] 未定义,因为我们正在尝试访问未定义的 [] 索引 [] (或 [].toString() ,即 '' ) .

    对不起以前的回答,我完全误读了你的评论 .

相关问题