当键名具有数字值时,JSON.parse()是否真的对属性进行排序? [英] Does JSON.parse() really sort properties when the key names have numeric values?

查看:108
本文介绍了当键名具有数字值时,JSON.parse()是否真的对属性进行排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里有很多关于这个问题的文章,它们都包含很多断言,可以总结如下:

There's a number of posts here about this issue, and they all contain a lot of assertions that can be summarized like this:

  1. 永远不能保证对象属性以任何方式排序.
  2. JSON.parse()从不以任何方式对属性进行排序.
  1. Object properties are never guaranteed to be ordered in any way.
  2. JSON.parse() never sorts properties in any way.

显然,我们对上面的#1毫无疑问,因此我们可以合理地预期,对于任何操作,属性仅按照它们出现的顺序进行处理.

Obviously we tend to have no doubt about #1 above, so we may reasonably expect that, for any operation, properties are processed merely in the order they appear.
[edit, following the @Bergi's comment: or at least they should appear in a random order]

然后我们可以特别推断出#2应该是真实的.

Then from that we might especially infer that #2 should be true.

但是请看以下代码片段:
(顺便说一句:为显示结果,下面的代码片段不使用console.log()本身可能会更改输出的顺序.相反,对象会由for (key in obj)进行迭代,并在文档中显示输出)

But look at this snippet:
(BTW note: to show the results, snippets below don't use console.log() which may itself change order of the output. Instead objects are iterated by for (key in obj) and the output displayed in the document)

var inputs = [
  '{"c": "C", "a": "A", "b": "B"}',
  '{"3": "C", "1": "A", "2": "B"}',
  '{"c": "C", "a": "A", "3": "C", "1": "A", "b": "B", "2": "B"}'
];

for (var i in inputs) {
  var json = inputs[i],
      parsed = JSON.parse(json),
      output = [];
  for (var j in parsed) {
    output.push(j + ': ' + parsed[j]);
  }
  document.write(`JSON: ${json}<br />Parsed: ${output.join(', ')})<hr />`);
}

它表明,给定一个具有无序键的JSON字符串:

It shows that, given a JSON string having unordered keys:

  • 当输入具有具有非数字值的键时,已解析对象的属性与输入中的顺序相同.这与上面的#2假设是一致的.
  • 相反,当输入具有带有数字值的(尽管它们是字符串,因此不会引发解析错误)时,解析对象的属性已排序.现在,这与#2假设矛盾.
  • 更多:当存在数字和非数字键值混合时,首先显示已排序的数字属性,然后在其原始属性中显示非数字属性订单.
  • When the input has keys with non-numeric values, the parsed object has its properties in the same order than in the input. This is consistent with the #2 assumption above.
  • Conversely when the input has keys with numeric values (though they're strings, so not firing parse error), the parsed object has its properties sorted. This now contradicts the #2 assumption.
  • More: when there are mixed numeric and non-numeric key values, first appear the numeric properties sorted, then the non-numeric properties in their original order.

首先,我很想得出一个结论,那就是实际上会有(未记录的?)功能,因此JSON.parse()遵循上面公开的规则"进行工作.

From that I was first tempted to conclude that actually there would be a (non-documented?) feature, so JSON.parse() works following the "rules" exposed above.

但是我有进一步研究的想法,因此下面的代码片段显示了仅编码对象的属性的排序方式:

But I had the idea to look further, so the snippet below now shows how ordered are the properties of a merely coded object:

var objects = [
  [
    '{"c": "C", "a": "A", "b": "B"}',
    {"c": "C", "a": "A", "b": "B"}
  ],
  [
    '{"3": "C", "1": "A", "2": "B"}',
    {"3": "C", "1": "A", "2": "B"}
  ],
  [
    '{"c": "C", "a": "A", "3": "C", "1": "A", "b": "B", "2": "B"}',
    {"c": "C", "a": "A", "3": "C", "1": "A", "b": "B", "2": "B"}
  ]
];

for (var i in objects) {
  var object = objects[i],
      output = [];
  for (var j in object[1]) {
    output.push(j + ': ' + object[1][j]);
  }
  document.write(`Code: ${object[0]}<br />Object: ${output.join(', ')}<hr />`);
}

它会产生类似的观察结果,即按照它们的编码顺序,其属性将按照上面的第3条规则进行存储:

It results in analogue observations, i.e. whichever order they're coded, properties are stored following the 3rd rule above:

  • 以数字命名的属性全部放在第一位,并进行排序
  • 接下来设置其他属性,按编码顺序

因此,这意味着不涉及JSON.parse():实际上,这似乎是对象构建的基本过程.
再次,这似乎没有记录,至少在我能找到的地方.

So it means that JSON.parse() is not involved: in fact it seems to be a fundamental process of object building.
Again this appears not documented, at least as far I could find.

关于真实,权威规则的任何线索吗?

Any clue for a real, authoritative, rule?

实际上,综合看来:

  • 此行为符合 ECMA规范规则.
  • 此规则应适用于保证特定顺序的所有方法,但在其他情况下是可选的.
  • 但是,现代浏览器似乎都选择应用规则,无论涉及哪种方法,因此都存在明显的矛盾.
  • This behaviour conforms to an ECMA specification rule.
  • This rule should apply to all methods where a specific order is guaranteed but is optional for other cases.
  • However it seems that modern browsers all choose to apply the rule whatever method is involved, hence the apparent contradiction.

推荐答案

对象的属性没有顺序,因此JSON.parse不能对它们进行排序.但是,当您列出或枚举对象的属性时,顺序可能没有明确定义.

The properties of an object have no order, so JSON.parse can't sort them. However, when you list or enumerate the properties of an object, the order may be well-defined or not.

不一定是for...in循环,也不一定是Object.keys

Not necessarily for for...in loops nor Object.keys

中充分解释的那样,ES6是否为对象属性引入了定义明确的枚举顺序?,即规格

未指定枚举属性的机制和顺序

The mechanics and order of enumerating the properties is not specified

但是对于OrdinaryOwnPropertyKeys是

对象具有内部[[OwnPropertyKeys]]方法,例如,Object.getOwnPropertyNamesObject.getOwnPropertySymbols使用该方法.

Objects have an internal [[OwnPropertyKeys]] method, which is used for example by Object.getOwnPropertyNames and Object.getOwnPropertySymbols.

对于普通对象,该方法使用 OrdinaryGetOwnProperty 抽象操作,它以明确定义的顺序返回属性:

In the case of ordinary objects, that method uses the OrdinaryGetOwnProperty abstract operation, which returns properties in a well-defined order:

使用调用抽象操作OrdinaryOwnPropertyKeys时 对象 O ,请执行以下步骤:

When the abstract operation OrdinaryOwnPropertyKeys is called with Object O, the following steps are taken:

  1. 为新的空
  1. Let keys be a new empty List.
  2. For each own property key P of O that is an integer index, in ascending numeric index order
  1. 添加 P 作为的最后一个元素.
  1. Add P as the last element of keys.

  • 对于 O 的每个自己的属性键 P ,它是一个字符串,但不是 整数索引,按属性创建的升序排列

  • For each own property key P of O that is a String but is not an integer index, in ascending chronological order of property creation

    1. 添加 P 作为的最后一个元素.
    1. Add P as the last element of keys.

  • 对于每个自己的作为符号的 O 的属性键 P ,按属性创建的时间顺序升序排列

  • For each own property key P of O that is a Symbol, in ascending chronological order of property creation

    1. 添加 P 作为的最后一个元素.
    1. Add P as the last element of keys.

  • 返回.
  • Return keys.

  • 因此,由于OrdinaryOwnPropertyKeys需要一个顺序,因此实现可以决定以该顺序在内部存储属性,并在枚举时也使用该属性.这就是您观察到的,但是您不能依靠它.


    Therefore, since an order is required by OrdinaryOwnPropertyKeys, implementations may decide to internally store the properties in that order, and use it too when enumerating. That's what you observed, but you can't rely on it.

    还请注意,非普通对象(例如代理对象)可能具有另一种[[OwnPropertyKeys]]内部方法,因此即使使用Object.getOwnPropertyNames的顺序也可能有所不同.

    Also be aware non-ordinary objects (e.g. proxy objects) may have another [[OwnPropertyKeys]] internal method, so even when using Object.getOwnPropertyNames the order could still be different.

    这篇关于当键名具有数字值时,JSON.parse()是否真的对属性进行排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆