JavaScript和/或JSON需要解析器按照定义顺序枚举属性吗?

6

给定一个对象定义:

var o = {x :1, y:2, z: 3, b: 4, a: 5, m: 6, X: 7};

枚举时,Chrome 似乎 尊重属性定义的顺序:

for (var i in o) { console.log(i, o[i]); }

输出:

x 1
y 2
z 3
b 4
a 5
m 6
X 7

JavaScript和/或JSON是否规定了这种级别的顺序保留?

无论哪种情况,它都是可靠的吗?


据我所知,JSON对语言没有任何要求,它只定义了数据格式。 - Felix Kling
2个回答

9

不,Javascript规范明确指出它们定义上是无序的,不需要任何特定的枚举顺序。

请参见ECMAScript规范的12.6.4节

列举属性的机制和顺序...未被指定。


1
浏览器可能会将它们排序,但也可能不会。这种行为是未定义的。 - gen_Eric
3
该行为已被定义;只是在某一方面没有具体规定。ECMA-262确保迭代将恰好访问每个可枚举属性,并表示Object.keys必须按照与for...in循环中这些值出现的顺序相同的顺序产生键,特别是如果它对顺序有任何更强的保证。它只是不需要特定的顺序。 - cHao
@dandavis for (feature in features) { if (feature.isDetectable) { feature.useFeatureDetection() } else { feature.avoidLikeThePlague() } } - svidgen
2
@Paulpro:我希望谷歌坚持自己的立场,不要改变Chrome。但问题是,当在其他地方正常运行的糟糕代码在你的浏览器中出现问题时,人们不会说“这个网站的JS很烂”……他们会说“这个浏览器很烂”。 - cHao
1
@dan:无论你看到了什么,都不安全。即使是据称制定事实标准的人也没有明确规定,事实上的标准毫无意义。(请参见MDN文档中的for...in。)除非命令被明确指定,否则如果你依赖它,你正在编写本质上有缺陷的代码(只是暂时能够工作)。当你的代码出现问题时,你会抱怨浏览器错误,我们将不得不再次进行这个对话,我将不得不说“我告诉过你”,然后你将不得不去改变一堆代码。 - cHao
显示剩余16条评论

1

不能保证属性以定义的顺序出现。

一些浏览器将保留按定义顺序排列的属性,而其他浏览器则不会。

将JSON解析为JavaScript对象之外的内容时,JSON解析器可以保留源中的顺序,否则无法保证顺序。


可能保留字符串中遇到的键值对的顺序,但是它不能保证顺序的正确性,因为JSON规范也指出它们是无序的:“对象是零个或多个名称/值对的无序集合”。{"a": 1, "b": 2}{"b": 2, "a": 1}在JSON方面是相同的,因此解析器应将它们解析为结构也相同。 - Paul
@Paulpro:有趣,那么jQuery中的JSON解析器没有正确实现,因为它创建的对象中属性的顺序不同...(当然,在保留该顺序的浏览器中) - Guffa
在 PHP 中说关联数组仍然有顺序是不正确的,因为 PHP 无法保证特定的顺序。然而,在 Javascript 中,无法保证顺序,因为在 Javascript 中创建的对象也没有顺序。 - Paul
@Paulpro:你没有抓住重点,而且似乎你在试图表达自己的观点,但我并没有看到。你在说什么? - Guffa
我只是想说你回答中的最后一句话有误导性,因为在像 PHP 这样的语言中,使用解码到关联数组时也无法保证顺序,这并不是因为 PHP 不支持关联数组的顺序,而是在 JSON 方面是错误的。 - Paul
显示剩余6条评论

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