为什么在JavaScript中"3 [1, 2];"返回undefined?

15

我正在查看Gmail的一些AJAX调用,并注意到有时调用的返回值以数字开头。例如:(请注意,第一行后没有分号)

3 
[1, 2];
如果我将这段代码输入到JavaScript控制台中,会返回undefined。然而,如果第二个参数是数字或字符串,则会返回第二个参数的值。例如:
3
4

返回 4。

我猜他们这么做是为了防止 JSONP 类型的攻击,但是有人知道正在进行什么样的底层评估吗? 在第二个案例中,我认为在第一行后会“插入”一个分号,这样返回 4 就有意义了。然而,我想不出第一个表达式为什么会返回 undefined。


1
就安全性而言(Google可能意识到这一点,并放置了一个无意义的最后元素之类的东西),这比{"d":}包装器要糟糕得多 - 通过在Number原型上定义属性,可以确定最后一个元素的内容是否与某个值匹配。 (因此,如果有人打算以此修复Firefox 2-bug...请注意!=)) - Ry-
(是的,看起来 Gmail 中的最后一个数字总是“0”。无论如何...) - Ry-
啊,因为逗号运算符将返回其集合中的最后一个元素。非常有趣。 - patorjk
2个回答

10
这是因为ASI(自动分号插入)的工作原理。第一条语句被解释为:
3[1,2];

所以它是undefined。第二个被ASI解释为3;4;,即4
在某些情况下,ASI规则是反直觉的,例如您可能想知道数字和括号之间为什么没有分号?嗯,这是有原因的。阅读这些资源以获取更多详细信息:
- JavaScript自动插入分号(ASI)的规则是什么? - http://bclary.com/2004/11/07/#a-7.9.1 谷歌可能会给您更多结果。:)这就是为什么我们有永无止境的无分号JavaScript战争。

3
哦,我明白了,这是属性访问 :) 你得喜欢 JS 中 {}[]() 有多重意义。 - Šime Vidas
@freakish:你可以指出具体的ASI规则吗? - Bergi
123 ['foo'] - 在数字字面量上访问属性。感谢Brendan提供这个。:P - Šime Vidas
在控制台中输入以下内容:['a', 'b', 'c']\n[1,2](中间有一个换行符):你会得到'c'。这证实了freakish的发现。 - Denys Séguret
2
据我所记,只有在遇到有问题的标记时才会插入分号。在这种情况下,在 3 之后的 [ 不是有问题的标记,因此引擎不会执行自动分号插入。 - Šime Vidas
显示剩余2条评论

7
这是为了防止Ajax JSON攻击更改Array构造函数。这是一个旧的漏洞,在现代浏览器中不相关,但必须加以处理。
该攻击覆盖了Array构造函数,因此当读取JSON时,代码将执行构造函数所做的操作。更多解释请参见:http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx 顺便说一句,这就是为什么ASP.NET始终发送此类对象的原因:{d: []}

我认为原帖作者知道这一点,但实际问题是:“为什么第一个语句返回undefined,而第二个语句却不会”。 - Bergi
@Bergi 哦,那是我的错。我把答案留下来,因为它部分回答了他的问题。 - Florian Margaine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接