3

I ran into the oddest behavior while working on a ticket this morning. If you see below after running Object.keys, the order of the keys has changed leaving P after F.

I tried the following:

  • Object.entries - got the same result as Object.keys
  • For loop - got the same result as Object.keys
  • I thought perhaps that the # was throwing off the sorting, so I removed it and re ran the test. - got the same result as Object.keys

I looked at the ECMAScript spec and this should not be case. Any ideas what could be causing this behavior ?

enter image description here

P.S I fixed the issue by running .sort() on the array but was curious to know what's causing the keys to go out of order.

  • 5
    As far as I know, the spec does not tell anyone how to order keys. Keys are ordered by the browser in different ways. You should never rely on the order of keys, that's what an `Array` is for. – somethinghere Sep 23 '19 at 13:31
  • 2
    order of keys is not guaranteed in javasciprt, however most of the time the string keys are in order they were added in – Krzysztof Krzeszewski Sep 23 '19 at 13:32
  • @KrzysztofKrzeszewski what does this mean most of the time, either it is or it is not or are we talking about different browser implementation – eugsun Sep 23 '19 at 13:35
  • 1
    The ordering *behavior* is defined by the spec, but the order has nothing to do with the property names other than that "number" property names come before others. The fact remains that relying in any way on object property name ordering is an extremely fragile coding practice. – Pointy Sep 23 '19 at 13:35
  • If you clear cache and run it again. it's gonna show the same order? – Qui-Gon Jinn Sep 23 '19 at 13:35
  • In the spec, there looks to be no re-ordering happening https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf does that imply the keys should be returned in the order that we see them ? –  Sep 23 '19 at 13:37
  • @Qui-GonJinn cleared cache, same order. –  Sep 23 '19 at 13:38
  • If a property "X" is removed and re-added, the ordering will change. That's why reliance on ordering is fragile; the object *looks* the same for most purposes, and property access works as expected, but ordering may change. – Pointy Sep 23 '19 at 13:38
  • i recommend reading this answer that describes which methods guarantee the order specified [methods-order](https://stackoverflow.com/a/38218582/10429793) – Krzysztof Krzeszewski Sep 23 '19 at 13:41

2 Answers2

2

So you are trying to turn a Map (unordered) into an Array (ordered). Some browsers dump the keys based on the order they are added to the object. Some do it other ways. Since it is browser dependent the best you can aim for is sorting said list.

I would suggest that after you dump it to an array, you should .sort() it how you see fit. It accepts a function you would need. Granted, it is case specific, so you would need to likely leverage the optional passed in function for sort to compare it in the way which best works for your use case. Since sort's inputs can be as complex as you like, you could also use it to sort on the contents of said values instead of just the keys.

Fallenreaper
  • 8,518
  • 10
  • 53
  • 107
0

As explained in this SO Answer,

[Objects are] an unordered collection of properties

Storing items by key in an object is very useful in order to retrieve them in one jump (when you know the key) but you lose the order. If you need to keep thinks in a specific order, always use arrays instead. So instead of having this object :

{
  "key1": {
    "name": "Jeff",
    "job": "Bartender"
  },
  "key2": {
    "name": "Jawad",
    "job": "Bus driver"
  }
}

You would have this array :

[
  {
    "any_unique_identifier_key": "key1",
    "name": "Jeff",
    "job": "Bartender"
  },
  {
    "any_unique_identifier_key": "key2",
    "name": "Jawad",
    "job": "Bus Driver"
  }
]

The downside is that when you are looking for a specific element in the array, you have to iterate through the whole thing (or use binary trees).

Ki Jéy
  • 2,201
  • 14
  • 29