JavaScript是否保证对象属性顺序?

JavaScript是否保证对象属性顺序?,javascript,object,Javascript,Object,如果我创建这样的对象: var obj = {}; obj.prop1 = "Foo"; obj.prop2 = "Bar"; 生成的对象总是这样吗 { prop1 : "Foo", prop2 : "Bar" } 也就是说,属性的顺序是否与我添加它们的顺序相同?在撰写本文时,大多数浏览器返回属性的顺序与插入属性的顺序相同,但这显然不能保证行为,因此不应依赖于此 过去人们常说: 枚举属性的机制和顺序。。。未指定 但是,在ES2015和更高版本中,非整数键将以插入顺序返回。对象的迭代顺序自ES

如果我创建这样的对象:

var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";
生成的对象总是这样吗

{ prop1 : "Foo", prop2 : "Bar" }

也就是说,属性的顺序是否与我添加它们的顺序相同?

在撰写本文时,大多数浏览器返回属性的顺序与插入属性的顺序相同,但这显然不能保证行为,因此不应依赖于此

过去人们常说:

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


但是,在ES2015和更高版本中,非整数键将以插入顺序返回。

对象的迭代顺序自ES2015以来一直遵循,但它(并不总是)遵循插入顺序。简单地说,迭代顺序是字符串键的插入顺序和数字键的升序的组合:

// key order: 1, foo, bar
const obj = { "foo": "foo", "1": "1", "bar": "bar" }
使用数组或数组可以更好地实现这一点<代码>地图与
对象
有一些相似之处,毫无例外:

贴图中的键是有序的,而添加到对象中的键不是有序的。因此,当对其进行迭代时,贴图对象将按插入顺序返回关键帧。(请注意,在ECMAScript 2015规范中,对象确实保留了字符串和符号键的创建顺序,因此仅使用ie字符串键遍历对象将按插入顺序生成键)

请注意,在ES2015之前,对象中的属性顺序根本无法保证。对象的定义来自:

4.3.3目标 对象是 输入对象它是一个无序的属性集合每个属性 包含基元值、对象或 功能。存储在数据库中的函数 对象的属性称为 方法

从:

对象是零个或多个名称/值对的无序集合,其中名称是字符串,值是字符串、数字、布尔值、null、对象或数组

(我的重点)

因此,不,您不能保证顺序。

是(对于非整数键)。

大多数浏览器将对象属性迭代为:

  • 按升序排列的整数键(以及像“1”这样解析为整数的字符串)
  • 按插入顺序排列的字符串键(ES2015保证所有浏览器都符合此要求)
  • 符号名称,按插入顺序(ES2015保证这一点和所有浏览器都符合)
  • 一些较旧的浏览器将类别#1和#2组合在一起,按插入顺序迭代所有键。如果您的键可能解析为整数,那么最好不要依赖任何特定的迭代顺序

    当前语言规范(自ES2015起)保留插入顺序,但解析为整数的键(如“7”或“99”)除外,其行为因浏览器而异。例如,当键解析为数字时,Chrome/V8不遵守插入顺序

    旧语言规范(ES2015之前):迭代顺序在技术上未定义,但所有主要浏览器都符合ES2015行为

    请注意,ES2015行为是由现有行为驱动的语言规范的一个很好的例子,而不是相反。为了更深入地了解这种向后兼容性思维,请参阅一个Chrome bug,它详细介绍了Chrome迭代顺序行为背后的设计决策。 根据对该bug报告的一个(相当固执己见的)评论:

    标准总是遵循实现,这就是XHR的来源,而谷歌也通过实现Gears,然后采用等价的HTML5功能来做同样的事情。正确的解决方法是让ECMA将事实上的标准行为正式纳入规范的下一版本


    正如其他人所说,当您迭代对象的属性时,您无法保证顺序。如果需要多个字段的有序列表,我建议创建一个对象数组

    var myarr = [{somfield1: 'x', somefield2: 'y'},
    {somfield1: 'a', somefield2: 'b'},
    {somfield1: 'i', somefield2: 'j'}];
    

    通过这种方式,您可以使用常规for循环并具有插入顺序。然后,如果需要,您可以使用数组排序方法将其排序为新数组。

    在现代浏览器中,您可以使用
    映射
    数据结构而不是对象

    贴图对象可以按插入顺序迭代其元素


    整个答案是在符合规范的情况下给出的,而不是任何引擎在特定时刻或历史上所做的

    一般来说,没有 实际问题非常模糊

    属性的顺序是否与我添加它们的顺序相同

    在什么情况下

    答案是:这取决于许多因素。一般来说,没有

    有时候,是的 这里是普通
    对象的属性键顺序:

    • 符合ES2015标准的发动机
    • 自有财产
    • Object.getOwnPropertyNames()
      Reflect.ownKeys()
      Object.getOwnPropertySymbols(O)
    在所有情况下,这些方法都包括由
    [[OwnPropertyKeys]]
    指定的不可枚举的属性键和顺序键(见下文)。它们所包含的键值类型不同(
    String
    和/或
    Symbol
    )。在此上下文中,
    字符串
    包括整数值

    返回
    O
    自己的
    String
    键控属性(属性名称)

    返回
    O
    自己的
    String
    -和
    Symbol
    -键控属性

    返回
    O
    自己的
    Symbol
    键控属性

    顺序基本上是:按升序排列的整数类
    字符串
    ,按创建顺序排列的非整数类
    字符串
    ,按创建顺序排列的符号。根据调用此函数的函数,可能不包括其中的某些类型

    特定语言是按以下顺序返回密钥:

  • 。。。
    O
    [正在迭代的对象]的每个属性键
    P
    ,都是整数索引,以升序数字索引顺序排列

  • 。。。每个属性键
    Pconst o = Object.create(null, {
      m: {value: function() {}, enumerable: true},
      "2": {value: "2", enumerable: true},
      "b": {value: "b", enumerable: true},
      0: {value: 0, enumerable: true},
      [Symbol()]: {value: "sym", enumerable: true},
      "1": {value: "1", enumerable: true},
      "a": {value: "a", enumerable: true},
    });
    
    Object {
      0: 0,
      1: "1",
      2: "2",
      b: "b",
      a: "a",
      m: function() {},
      Symbol(): "sym"
    }
    
    const obj = {};
    obj.prop1 = "Foo";
    obj.prop2 = "Bar";
    obj['1'] = "day";
    console.log(obj)
    
    **OUTPUT: {1: "day", prop1: "Foo", prop2: "Bar"}**
    
        const myMap = new Map()
        // setting the values
        myMap.set("foo", "value associated with 'a string'")
        myMap.set("Bar", 'value associated with keyObj')
        myMap.set("1", 'value associated with keyFunc')
    
    OUTPUT:
    **1.    ▶0: Array[2]
    1.   0: "foo"
    2.   1: "value associated with 'a string'"
    2.  ▶1: Array[2]
    1.   0: "Bar"
    2.   1: "value associated with keyObj"
    3.  ▶2: Array[2]
    1.   0: "1"
    2.   1: "value associated with keyFunc"**