如果我创建一个这样的对象:

var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";

生成的对象总是这样吗?

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

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


当前回答

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

开发人员mozilla >地图

Map对象可以按插入顺序迭代其元素…

其他回答

这是我吃了不少苦头才知道的。

使用React和Redux,我想遍历的键的状态容器,以生成子,每次存储被更改时都会刷新(根据Redux的不变性概念)。

因此,为了获取Object.keys(valueFromStore),我使用了Object.keys(valueFromStore).sort(),这样我至少现在有了键的字母顺序。

是(但不总是插入顺序)。

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

以升序排列的正整数键(以及像“1”这样解析为整型的字符串) 字符串键,按插入顺序(ES2015保证这一点,所有浏览器都遵守) 符号名称,按插入顺序(ES2015保证这一点,所有浏览器都遵守)

一些较老的浏览器结合了类别#1和#2,按插入顺序迭代所有键。如果您的键可能被解析为整数,最好不要依赖于任何特定的迭代顺序。

当前语言规范(自ES2015起)的插入顺序保持不变,除非键解析为正整数(如“7”或“99”),在不同浏览器中行为不同。例如,当键被解析为数字时,Chrome/V8不尊重插入顺序。

旧的语言规范(在ES2015之前):迭代顺序在技术上没有定义,但所有主流浏览器都遵守ES2015行为。

请注意,ES2015行为是语言规范由现有行为驱动的一个很好的例子,而不是相反。要更深入地了解向后兼容的心态,请参阅http://code.google.com/p/v8/issues/detail?id=164,这是一个Chrome bug,详细介绍了Chrome迭代顺序行为背后的设计决策。 根据对该错误报告的(相当固执己见的)评论:

标准总是跟着实现走的,XHR就是这么来的,谷歌通过实现Gears,然后拥抱等价的HTML5功能来做同样的事情。正确的解决方法是让ECMA正式地将事实上的标准行为纳入规范的下一个版本中。

对于一个100%故障安全的解决方案,你可以使用嵌套对象,并像这样做:

const obj = {};
obj.prop1 = {content: "Foo", index: 0};
obj.prop2 = {content: "Bar", index: 1};

for (let i = 0; i < Object.keys(obj).length; i++)
for (const prop in obj) {
    if (obj[prop].index == i) {
        console.log(obj[prop].content);
        break;
    }
}

在JavaScript中,普通对象中的属性顺序是一个复杂的主题。

虽然在ES5中没有明确地指定顺序,但ES2015在某些情况下定义了顺序,此后规范的连续更改越来越多地定义了顺序(甚至在ES2020中定义了for-in循环的顺序)。给定的是以下对象:

const 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"
}

“拥有”(非继承)属性的顺序是:

类似正整数的键,按升序排列 按插入顺序排列的字符串键 符号插入顺序

因此,有三个段,它们可以改变插入顺序(如示例中所发生的那样)。类似正整数的键完全不遵循插入顺序。

在ES2015中,只有特定的方法遵循以下顺序:

Object.assign Object.defineProperties Object.getOwnPropertyNames Object.getOwnPropertySymbols Reflect.ownKeys JSON.parse JSON.stringify

截至ES2020,所有其他都有(一些在ES2015和ES2020之间的规格,其他在ES2020),其中包括:

对象。钥匙,对象。条目,对象。值,… 对. .

最难确定的是for-in,因为它独特地包含继承属性。这在ES2020中已经完成了(除了边缘情况)。以下列表来自链接的(现在已经完成)提案,提供了未指定顺序的边缘情况:

Neither the object being iterated nor anything in its prototype chain is a proxy, typed array, module namespace object, or host exotic object. Neither the object nor anything in its prototype chain has its prototype change during iteration. Neither the object nor anything in its prototype chain has a property deleted during iteration. Nothing in the object's prototype chain has a property added during iteration. No property of the object or anything in its prototype chain has its enumerability change during iteration. No non-enumerable property shadows an enumerable one.

结论:即使在ES2015中,你也不应该依赖JavaScript中普通对象的属性顺序。它很容易出错。如果需要有序的命名对,则使用Map,它只使用插入顺序。如果只需要排序,则使用数组或Set(也使用纯插入顺序)。

来自JSON标准:

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

(强调我的)。

所以,不,你不能保证订单。