44

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

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

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

这涉及隐式类型转换,我试图了解这一行是如何解释的。

我已经隔离了每个角色

  • (![]+[])[+[]]印刷"f"
  • (![]+[])[+!+[]]印刷"a"
  • ([![]]+[][[]])[+!+[]+[+[]]]印刷"i"
  • (![]+[])[!+[]+!+[]]印刷"l"

我还设法分解了返回每个字母的表达式,除了"i"

"f"

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

false+[]根据第 11.6.1 点,二元+运算符的两个参数都转换为字符串,因此我们得到"false"+"",它计算"false"

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

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

"a"

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

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

!0评估为第 9.2节和第 11.4.9true节中定义的值。首先,转换为布尔值,然后运算符反转该值。0false

+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 规则的链接。

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

4

2 回答 2

39

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

[]['']

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

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

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

当使用字符串访问数组的属性并且该字符串恰好是数组的一个元素时,该字符串被强制转换为整数,然后您将返回数组的实际元素:

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

所以你的最终结果是:

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

阅读此答案以了解该部分的说明[false] + undefined

于 2013-06-09T22:37:34.460 回答
1

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

([![]]+[][[]])另一个是你自己发现的。

![]返回false。然后我们[...]用来获取 的.toString()行为+。(与) the is undefined[]+[]相同,因为我们试图访问未定义的索引(或, is )。[].toString()+[].toString()[][[]][][].toString()''[]

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

于 2013-06-09T22:36:37.277 回答