Javascript - 从对象开始维护关键顺序 - >排列

时间:2015-07-14 14:12:03

标签: javascript

我知道JS对象不保证密钥顺序,但是,我的数据结构来自我无法控制的后端。从以下地方开始,我可以做些什么来保存关键顺序:

var obj = {
   foo: 'bar',
   bar: 'foo' 
};

为:

Object.keys(obj); // hoping for ['foo', 'bar']

最重要的是,我不幸地保留了关键顺序......

3 个答案:

答案 0 :(得分:4)

没有。正如你写的那样:

  

我知道JS对象中没有保证关键顺序

如果您需要订单,则需要使用数组。如果您有一个对象,则属性没有已定义的顺序。

答案 1 :(得分:1)

ECMA-262未指定枚举顺序。事实上的标准是匹配插入顺序。

虽然对数组索引的枚举顺序(即,可以解析为integer的属性名称)没有给出任何保证,因为数组索引的插入顺序会产生大量内存 开销。

编辑: 添加了jsfiddle example

var obj1 = {
   a: 'test1',
   b: 'test2' 
};

var obj2 = {
   2: 'test1',
   1: 'test2' 
};
// max 32bit unsigned is 2,147,483,647
var obj3 = {
   2147483649: 'test1',
   2147483648: 'test2' 
};
// max 64bit unsigned is 9,223,372,036,854,775,807
var obj4 = {
   9223372036854770: 'test1',
   9223372036854768: 'test2',
};

// != number < 2,147,483,647, order is not changed
console.log(Object.keys(obj1));
// < 2,147,483,647, order is changed
console.log(Object.keys(obj2));
// > 2,147,483,647, order is not changed in Firefox, but changed in Chrome
console.log(Object.keys(obj3));
// > 9,223,372,036,854,775,807, order is not changed in neither Firefox or Chrome
console.log(Object.keys(obj4));

这意味着Chrome的javascript引擎V8会订购任何64bit unsigned个号码,而Firefox的javascript引擎SpiderMonkey会订购任何32bit unsigned个数字。

答案 2 :(得分:1)

JSON specification表示

  

对象是零个或多个名称/值对的无序集合...

严格来说,文字JSON文本当然有一个顺序:文本不会突然自我扰乱。但是,您希望的行为 - 一组有序的名称/值对 - 不是JSON提供的构造。您希望对象表示法提供超出JSON规范所要求的语义的语义含义。

顺便说一下,在JSON中执行此操作

{
    "foo": "baz",
    "bar": "egg" 
}

是无序集的描述。如果您打算用它来描述有序集,那么您就不会遵循JSON规则。数据恰好是有序的(因为这就是字符序列的工作原理),但是当考虑输入字符串中存在的数据时,JSON语义可以自由地允许实现完全忽略名称/值对的顺序。

您可以编写直接在JSON输入字符串上运行的代码,以便以某种方式解析键的输入顺序来解析文本,但不需要JSON解析器实现来为您提供该功能。

正确的JSON-idiomatic解决方案是在JSON响应中提供一组键名:

{
    data: {
        "foo": "baz",
        "bar": "egg" 
    },
    order: ["foo", "bar"]
}

显然,如果您不控制响应,则不能这样做。通过选择表示对象中的数据,响应的作者断言键的顺序纯粹是任意的。如果JSON的作者打算断言密钥条目的顺序,那么该断言是JSON规则的外部。

实际上,大多数JavaScript引擎通常会选择按照其属性的创建顺序报告密钥名称。但是,任何规范都不要求这种行为(并且在边缘情况下有时不一致),因此引擎和版本之间在法律上可能不同。