最近我在Firefox中发现了这种奇怪的行为:
此代码自动对属性进行排序:
var an_obj = { "4": "d", "1": "a", "2": "c"};
alert(Object.keys(an_obj)); // will alert "1, 2, 4"
虽然这不是:
var value2 = {"1003":1, "1001":2, "1000":3};
alert(Object.keys(value2));// will alert "1003, 1001, 1000"
任何大于1000的数字在Firefox中都会有不同的行为,而其他浏览器(Chrome,IE11)的行为将与预期的自动排序数字大于1000一样。
我相信这是FireFox中的一个错误,我错了吗?
更新1
这使得命令在FireFox的相同实现中“不可预测”。我可以理解不完全排序的数值或相应地排序一个标准,但在“任意”数字之后不会表现为“不可预测”。
答案 0 :(得分:6)
这不是错误。对象不保证其属性中的任何顺序,并且在某些情况下不应依赖Object.keys
的任何顺序。
在§15.2.3.14 ECMAScript 5 standard中说明了Object.keys
如果实现为for-in语句定义了特定的枚举顺序,则必须在此算法的步骤5中使用相同的枚举顺序。
这意味着for-in
语句和Object.keys
的任何排序都完全取决于实现。
答案 1 :(得分:2)
ECMAScript standard没有为Object.keys
返回的属性定义排序,而是将其留给实现:
如果实现定义了枚举的特定顺序 for-in语句,必须在步骤5中使用相同的枚举顺序 这个算法。
至于Firefox使用的具体实现,MDN states:
属性的顺序与通过手动循环对象的属性给出的顺序相同。
事实上,如果你尝试一下,你会发现情况确实如此:
for(var o in {"1003":1, "1001":2, "1000":3})
console.log(o);
// 1003, 1001, 1000
对结果的排序没有其他保证。换句话说,它不是一个错误,它只是不同实现的本质的一部分。但如果你愿意,可以称之为 quirk 。
答案 2 :(得分:1)
我想添加一个我自己的问题,我发现有人已经将这种行为提交给了Firefox团队:
@Peter Olson和@ p.s.w.g正确解释的答案是:
是的,枚举排序未指定。不要依赖它!
ES7应该纠正这个问题,而关于这个问题的最终决定是咬紧牙关并让它无法解决。
对于对此感兴趣的人,您可以在此处找到完整的参考资料:
答案 3 :(得分:0)
您可以使用sort来修复不可预测的行为。我假设您已经知道这一点并且正在尝试获取有关可能的错误的反馈,但是如果您没有,或者其他人需要知道:
var value2 = {"1003":1, "1001":2, "1000":3};
var sorted = Object.keys(value2);
sorted.sort();
alert(sorted);
在firefox中以预期的方式呈现值。