JavaScript浏览器怪异行为 - 数组长度

27

代码:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Unusual Array Lengths!</title>

    <script type="text/javascript">
        var arrayList = new Array();
        arrayList = [1, 2, 3, 4, 5, ];
        alert(arrayList.length);
    </script>

</head>
<body>
</body>
</html>

注意数组声明中的额外逗号。上面的代码在不同的浏览器上会给出不同的输出:

Safari: 5

Firefox: 5

IE: 6

Safari和Firefox忽略了数组中多余的逗号,而IE将其视为数组中的另一个对象。

在一些搜索中,我发现有关哪个答案是正确的的意见不一。大多数人认为IE是正确的,但Safari也像Firefox一样做同样的事情。我没有在Opera等其他浏览器上测试过这个问题,但我认为存在差异。

我的问题:

i. 哪个是正确的?

编辑:根据普遍共识(以及ECMAScript指南),我们认为IE再次是有问题的。

ii. 还有其他类似的JavaScript浏览器怪异行为吗?

编辑:是的,有很多JavaScript怪癖。 www.quirksmode.org 是一个很好的资源。

iii. 如何避免这些错误?

编辑:使用JSLint来验证你的JavaScript代码。或者使用一些外部 。或者清理你的代码。

感谢DamienBJasonBuntingJohnKonrad Rudolph提供的意见。


2
非常感谢!非常感谢!非常感谢!一个愚蠢的额外逗号导致IE8的行为与FireFox不同,这让我疯狂地想要找出问题所在! - Tom
感谢您提出这个问题,帮助我解决了IE无法按预期处理数组的问题。 :) - Nathan Pitman
1
谢谢。当我检查数组元素的长度时,我遇到了IE8 JavaScript错误。原因是在数组声明中有一个额外的逗号。 - jamesnotjim
7个回答

9
我认为Firefox的行为是正确的。IE中的第6个值是多少(很抱歉我没有方便测试)。由于没有提供实际值,我想它会用类似“null”的东西来填充,这显然不是您创建数组时想要发生的事情。
但归根结底,哪种方式是“正确”的并不重要,因为现实情况是:无论您只针对一个浏览器,还是针对多个浏览器,您的代码都需要在所有浏览器上运行。在这种情况下,明显的解决方案是永远不要在数组初始化程序中包含悬挂逗号。
如果您遇到了避免它的问题(例如出于某种原因您已经养成了(我认为不好的)习惯),那么像JSLint这样的东西可能会有所帮助。

7
我很感兴趣,所以我在ECMAScript 262 ed. 3的定义中查找了相关内容,这是JavaScript 1.8的基础。相关定义在第11.1.4节中找到,但不幸的是并不是非常清楚。该部分明确指出,在开头或中间省略的元素不会被定义为一个元素,但会对总长度有贡献。
没有关于初始化器末尾多余逗号的明确说明,但通过省略,我得出上述声明意味着它们不会对总长度产生贡献,因此我得出MSIE是错误的结论。
相关段落如下:
数组元素可以在元素列表的开头、中间或结尾处省略。每当元素列表中的逗号不是由赋值表达式(即在逗号之前或之后的逗号)引导时,缺失的数组元素会对数组的长度和后续元素的索引增加做出贡献。省略的数组元素未被定义。

Konrad:“相关的定义可以在第11.1.4节找到,但不幸的是并不是很清楚。” 对我来说,它似乎很清楚:“只有当元素列表中的逗号不是由一个赋值表达式_前置_时[...]”。 只有在省略了逗号之前的表达式时,它才会被计算为一个元素([, foo] => 2个元素)。没有提到逗号之后缺少表达式的情况([foo, ] => 1个元素)。IE有问题。 - Zuu
我同意这并不清晰。从生产定义ArrayLiteral: [ElementList,Elisionopt]: ... 让pad成为评估省略的结果;如果不存在,则使用数字值零。 ... 使用参数“length”,ToUint32(pad + len)和false调用数组的[[Put]]内部方法。 - Chris
对我来说,这个定义的意思是将长度设置为省略号(填充)的长度加上前面元素列表的长度。如果我没有正确理解,请有人告诉我。 - Chris

3
“3”通常用于这些情况,我通常会在我的脚本中添加它。
if(!arrayList[arrayList.length -1]) arrayList.pop();

你可以将其制作成实用函数。

2
那么如果最后一个元素是0或"",它就会被删除吗? - mplungjan
3
如果(typeof arrayList[arrayList.length-1] === "undefined"),则去掉arrayList的最后一项(pop()函数)。 - Tracker1

2
首先,Konrad 引用规范是正确的,因为规范定义了语言并回答了你的第一个问题。
回答你的其他问题:

还有其他类似的 JavaScript 浏览器特性需要注意吗?

哦,太多了,无法在此列出!可以尝试访问 QuirksMode 网站,那里几乎包含了所有已知的问题。

如何避免这些错误?

最好的方法是使用 一个库 来为你抽象这些问题,以便你可以专注于应用程序的逻辑。虽然有点晦涩,但我更喜欢并推荐 MochiKit

1
哪一个是正确的?
Opera也返回5。这意味着IE数量不足,多数规则适用于您应该期望什么。

1

Ecma 262第5.1版本第11.1.4节的数组初始化程序说明,如果数组末尾有逗号,则该逗号不会导致数组长度增加。"如果在数组末尾省略了某些元素,它们将不会对数组的长度产生贡献"

这意味着 [ "x", ] 是完全合法的JavaScript代码,并且应该返回一个长度为1的数组。


毫无疑问,规范非常清晰明了,明确指出“如果在数组末尾省略一个元素”,即被省略,“它不会对数组的长度产生影响”——这再清晰不过了。 - Austin France

0

@John:arrayList[5]的值结果为'undefined'。

是的,在声明中永远不应该有悬空逗号。实际上,我刚刚在浏览别人的很长的javascript代码时发现它在不同的浏览器中都无法正常工作。结果发现,悬空的逗号是意外输入的罪魁祸首!:)


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