【问题标题】:JS do not sort numeral object indicesJS 不对数字对象索引进行排序
【发布时间】:2020-07-10 13:15:59
【问题描述】:

当像这样创建对象时

let o = {}
o["prop2"] = "val"
o["prop1"] = "val"

属性是按照设置的顺序存储的,因此在获取对象的键 (Object.keys(o)) 时,它们会以 正确 的顺序返回 (["prop2", "prop1"])。这个顺序具有广泛的影响,因为for...in 循环使用它,因此JSON.stringify 也受到它的影响。我想将此行为用于性能优化(例如发送更易于解析的已排序对象)。

但是,当使用数字索引时,这一切都会崩溃。看似相似的物体

let o = {}
o["2"] = "val"
o["1"] = "val"

不确认上述行为。这里Object.keys(o) 返回["1", "2"] :(.

可以通过某种方式避免这种情况吗?没有预先/后修复所有属性?

【问题讨论】:

  • 这些是由于 ES 规范。由于历史原因和优化技术(整数访问可以高度优化,因为本机级别的数组访问和 React 等主要库都依赖它)。您可以使用 Map() 或为它们添加前缀,因此它们不是整数。
  • 尝试使用map,它们将保留插入顺序
  • @theblackgigant 地图如果我可以JSON.stringify 他们会很好用
  • 无论如何你都必须在以后反序列化它,所以取决于顺序通常是一个坏主意。简短的回答是否定的,你应该避免依赖于关键顺序
  • @MaximilianMairinger 在性能方面,需要真实世界的数据集和上下文才能使其相关。它可以根据从环境到数据集类型和大小到用例的所有因素而有很大差异。如果您对 JS 引擎似乎在做您认为不应该做的额外工作感到困扰,请知道该引擎在处理这些事情方面很可能比您手动做的更优化。内部数据的解析和表示不会是复杂性更高的数量级,并且很可能是相对于您自己的线性或恒定的。

标签: javascript loops object


【解决方案1】:

改用Map 来保留插入顺序。

let m = new Map;
m.set("2", "val");
m.set("1", "val");
m.forEach((v,k)=>console.log(k,"=",v));

要将其转换为 JSON,您可以对 Map 的条目进行字符串化。您可以使用解析字符串并将条目传递给 Map 的构造函数以将其转换回来。

const map = new Map([
  ['foo', 10],
  ['baz', 42]
]);
let str = JSON.stringify([...map.entries()])
console.log(str);
new Map(JSON.parse(str)).forEach((v,k)=>console.log(k,"=",v));

您可以为 JSON.stringify 和 JSON.parse 提供回调以转换嵌套的 Map 结构。

let m = new Map;
m.set("b", new Map([["c","d"],["e","f"], ["d", new Map([["a", 1]])]]));
let str = JSON.stringify(m, (key,val)=>{
    return Object.prototype.toString.call(val) === '[object Map]' ? [...val.entries()] : val;
});
console.log(str);
let m2 = JSON.parse(str, (key, val)=>{
    return Array.isArray(val) && Array.isArray(val[0]) ? new Map(val) : val;
});
console.log(m2);

演示:https://jsfiddle.net/ob8d2uLf/1/

【讨论】:

  • 如果属性 c 也是一个 Map,这会分崩离析,对吧?
  • @MaximilianMairinger 你可以实现一个回调函数到 JSON.stringify/parse 来处理它。 “reviver”/“replacer”功能
  • @hev1 我建议使用 reviver/replacer 功能,而不是手动递归遍历它。这种实现看起来也非常非常低效。
  • 这里有点意见,但如果它在这和只是前缀之间,或者有你自己的自定义对象表示法,比如 Map,或者存储一个键数组来保持顺序,我会说也许只是给它加上前缀并称之为一天,或者如果需要绝对性能,则使用键数组。并根据您的实际需要选择其中之一,其中每个都可能比其他更适合用例
  • @MaximilianMairinger 试试这个:jsfiddle.net/ob8d2uLf/1
猜你喜欢
  • 1970-01-01
  • 2022-10-14
  • 2015-10-19
  • 2013-11-29
  • 2012-12-26
  • 2023-03-21
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
相关资源
最近更新 更多