[javascript] Does JavaScript guarantee object property order?

If I create an object like this:

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

Will the resulting object always look like this?

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

That is, will the properties be in the same order that I added them?

This question is related to javascript object

The answer is


As others have stated, you have no guarantee as to the order when you iterate over the properties of an object. If you need an ordered list of multiple fields I suggested creating an array of objects.

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

This way you can use a regular for loop and have the insert order. You could then use the Array sort method to sort this into a new array if needed.


As of ES2015, property order is guaranteed for certain methods that iterate over properties. but not others. Unfortunately, the methods which are not guaranteed to have an order are generally the most often used:

  • Object.keys, Object.values, Object.entries
  • for..in loops
  • JSON.stringify

But, as of ES2020, property order for these previously untrustworthy methods will be guaranteed by the specification to be iterated over in the same deterministic manner as the others, due to to the finished proposal: for-in mechanics.

Just like with the methods which have a guaranteed iteration order (like Reflect.ownKeys and Object.getOwnPropertyNames), the previously-unspecified methods will also iterate in the following order:

  • Numeric array keys, in ascending numeric order
  • All other non-Symbol keys, in insertion order
  • Symbol keys, in insertion order

This is what pretty much every implementation does already (and has done for many years), but the new proposal has made it official.

Although the current specification leaves for..in iteration order "almost totally unspecified, real engines tend to be more consistent:"

The lack of specificity in ECMA-262 does not reflect reality. In discussion going back years, implementors have observed that there are some constraints on the behavior of for-in which anyone who wants to run code on the web needs to follow.

Because every implementation already iterates over properties predictably, it can be put into the specification without breaking backwards compatibility.


There are a few weird cases which implementations currently do not agree on, and in such cases, the resulting order will continue be unspecified. For property order to be guaranteed:

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.


From the JSON standard:

An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array.

(emphasis mine).

So, no you can't guarantee the order.


Property order in normal Objects is a complex subject in Javascript.

While in ES5 explicitly no order has been specified, ES2015 has an order in certain cases. Given is the following object:

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},
});

This results in the following order (in certain cases):

Object {
  0: 0,
  1: "1",
  2: "2",
  b: "b",
  a: "a",
  m: function() {},
  Symbol(): "sym"
}
  1. integer-like keys in ascending order
  2. normal keys in insertion order
  3. Symbols in insertion order

Thus, there are three segments, which may alter the insertion order (as happened in the example). And integer-like keys don't stick to the insertion order at all.

The question is, for what methods this order is guaranteed in the ES2015 spec?

The following methods guarantee the order shown:

  • Object.assign
  • Object.defineProperties
  • Object.getOwnPropertyNames
  • Object.getOwnPropertySymbols
  • Reflect.ownKeys

The following methods/loops guarantee no order at all:

  • Object.keys
  • for..in
  • JSON.parse
  • JSON.stringify

Conclusion: Even in ES2015 you shouldn't rely on the property order of normal objects in Javascript. It is prone to errors. Use Map instead.


Just found this out the hard way.

Using React with Redux, the state container of which's keys I want to traverse in order to generate children is refreshed everytime the store is changed (as per Redux's immutability concepts).

Thus, in order to take Object.keys(valueFromStore) I used Object.keys(valueFromStore).sort(), so that I at least now have an alphabetical order for the keys.


Major Difference between Object and MAP with Example :

it's Order of iteration in loop, In Map it follows the order as it was set while creation whereas in OBJECT does not.

SEE: OBJECT

const obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";
obj['1'] = "day";
console.log(obj)

**OUTPUT: {1: "day", prop1: "Foo", prop2: "Bar"}**

MAP

    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"**

In modern browsers you can use the Map data structure instead of a object.

Developer mozilla > Map

A Map object can iterate its elements in insertion order...


YES (for non-integer keys).

Most Browsers iterate object properties as:

  1. Integer keys in ascending order (and strings like "1" that parse as ints)
  2. String keys, in insertion order (ES2015 guarantees this and all browsers comply)
  3. Symbol names, in insertion order (ES2015 guarantees this and all browsers comply)

Some older browsers combine categories #1 and #2, iterating all keys in insertion order. If your keys might parse as integers, it's best not to rely on any specific iteration order.

Current Language Spec (since ES2015) insertion order is preserved, except in the case of keys that parse as integers (eg "7" or "99"), where behavior varies between browsers. For example, Chrome/V8 does not respect insertion order when the keys are parse as numeric.

Old Language Spec (before ES2015): Iteration order was technically undefined, but all major browsers complied with the ES2015 behavior.

Note that the ES2015 behavior was a good example of the language spec being driven by existing behavior, and not the other way round. To get a deeper sense of that backwards-compatibility mindset, see http://code.google.com/p/v8/issues/detail?id=164, a Chrome bug that covers in detail the design decisions behind Chrome's iteration order behavior. Per one of the (rather opinionated) comments on that bug report:

Standards always follow implementations, that's where XHR came from, and Google does the same thing by implementing Gears and then embracing equivalent HTML5 functionality. The right fix is to have ECMA formally incorporate the de-facto standard behavior into the next rev of the spec.


In ES2015, it does, but not to what you might think

The order of keys in an object wasn't guaranteed until ES2015. It was implementation-defined.

However, in ES2015 in was specified. Like many things in JavaScript, this was done for compatibility purposes and generally reflected an existing unofficial standard among most JS engines (with you-know-who being an exception).

The order is defined in the spec, under the abstract operation OrdinaryOwnPropertyKeys, which underpins all methods of iterating over an object's own keys. Paraphrased, the order is as follows:

  1. All integer index keys (stuff like "1123", "55", etc) in ascending numeric order.

  2. All string keys which are not integer indices, in order of creation (oldest-first).

  3. All symbol keys, in order of creation (oldest-first).

It's silly to say that the order is unreliable - it is reliable, it's just probably not what you want, and modern browsers implement this order correctly.

Some exceptions include methods of enumerating inherited keys, such as the for .. in loop. The for .. in loop doesn't guarantee order according to the specification.


At the time of writing, most browsers did return properties in the same order as they were inserted, but it was explicitly not guaranteed behaviour so shouldn't have been relied upon.

The ECMAScript specification used to say:

The mechanics and order of enumerating the properties ... is not specified.

However in ES2015 and later non-integer keys will be returned in insertion order.


This whole answer is in the context of spec compliance, not what any engine does at a particular moment or historically.

Generally, no

The actual question is very vague.

will the properties be in the same order that I added them

In what context?

The answer is: it depends on a number of factors. In general, no.

Sometimes, yes

Here is where you can count on property key order for plain Objects:

  • ES2015 compliant engine
  • Own properties
  • Object.getOwnPropertyNames(), Reflect.ownKeys(), Object.getOwnPropertySymbols(O)

In all cases these methods include non-enumerable property keys and order keys as specified by [[OwnPropertyKeys]] (see below). They differ in the type of key values they include (String and / or Symbol). In this context String includes integer values.

Object.getOwnPropertyNames(O)

Returns O's own String-keyed properties (property names).

Reflect.ownKeys(O)

Returns O's own String- and Symbol-keyed properties.

Object.getOwnPropertySymbols(O)

Returns O's own Symbol-keyed properties.

[[OwnPropertyKeys]]

The order is essentially: integer-like Strings in ascending order, non-integer-like Strings in creation order, Symbols in creation order. Depending which function invokes this, some of these types may not be included.

The specific language is that keys are returned in the following order:

  1. ... each own property key P of O [the object being iterated] that is an integer index, in ascending numeric index order

  2. ... each own property key P of O that is a String but is not an integer index, in property creation order

  3. ... each own property key P of O that is a Symbol, in property creation order

Map

If you're interested in ordered maps you should consider using the Map type introduced in ES2015 instead of plain Objects.