Traversal Order of Object Properties in JavaScript ES6
Tags: javascript, webdev, react
Published: 2020-09-04 00:59:09

Have you ever seen code that receives a `JSON` object response from a backend service then and uses that object to create React components?

```jsx
Object.keys(data).map((entry) => {
  <MyComponent key={entry.id} name={entry.name} ... />;
});
```

I have seen it many times :scream:, and while it might be ok in some cases, it's very risky! Especially if those `<MyComponent />`s need to be displayed in **the order they were received/inserted in.**

### ES6 Object Traversal 

Before ES6, the order in which object properties were traversed was left unspecified and so each engine handled it as it saw fit :grimacing:

With ES6, the traversal order was guaranteed for some methods:

* `Object.getOwnPropertyNames()`
* `Reflect.ownKeys()`
* `Object.getOwnPropertySymbols()`

But not others:

* `Object.keys()`
* `Object.values()`
* `Object.entries()`
* `JSON.stringify()`
* `for .. in` loops

As you may have noticed, the most popular methods are the ones that don't guarantee the order :unamused:

The ones that do guarantee it, follow the [[[OwnPropertyKeys]]](http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys) internal method which specifies the following order: 

* Integer indices (if applicable), in ascending order.
* Other string keys (if applicable), in property creation 
  order.
* Symbol keys (if applicable), in property creation order.

```jsx
const obj = {
  [Symbol('first')]: 'symbol: first'
  '5': 'integer: 5',
  'foo': 'string: foo',
  '01': 'string: 01',
  2: 'integer: 2',
};

console.log(Reflect.ownKeys(obj));
// ["2", "5", "foo", "01", Symbol(first) ]
```

### And what about those other popular methods like `Object.keys()`?

Although the current versions of some major browsers implement this very same order for those popular methods as well - ES6 implementations are **NOT** required to define a specific order of enumeration for those popular methods, so you would be better off not counting on it in your code. 
(I have personally seen this order **not working** on Safari 13.1.2 when i used `Object.keys()` in one of my projects :worried:)

### What are the alternatives?

Excluding some third-party libraries, if you are looking to guarantee iteration according to insertion order, an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) or a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) would be a safer choice!


### Is there any hope?

Well, actually.. **there is!** :heart_eyes_cat:

There was a [proposal](https://github.com/tc39/proposal-for-in-order) to change the ECMA specification and make this `[[OwnPropertyKeys]]` order behavior official for all of those popular object traversal methods as well, and that proposal has been [accepted and merged into the main specification](https://github.com/tc39/ecma262/pull/1791)!

This means that as of ES2020, **property order for these popular methods is guaranteed by the ECMA specification to be iterated over in the same deterministic manner as the other ones!**

## Conclusion

Object traversal order in JavaScript has always been tricky due to different browser implementations, but ES2020 has finally provided a deterministic order standard for all of the popular traversal methods. 
Still, this order might not work for you - your project might include objects with a mix of `integer` and `string` keys, yet require traversal according to insertion order. 

It's good to know how object traversal works, and it's also good to know that there are alternatives you could use :blush:

Happy coding!  :rocket: :rocket: :rocket: