2

I have this test:

let obj = {
    "5555555555": 5,
    "4444444444": 4,
    "3333333333": 3,
    "2222222222": 2,
};
console.log(Object.keys(obj));

The output is ["2222222222", "3333333333", "5555555555", "4444444444"]

However, the EcmaScript 2015 specification defines the order for [[OwnPropertyKeys]]:

  1. For each own property key P of O that is an integer index, in ascending numeric index order,
        a. Add P as the last element of keys.

And integer index is defined as:

An integer index is a String-valued property key that is a canonical numeric String and whose numeric value is either +0 or a positive integer ≤ 253−1. An array index is an integer index whose numeric value i is in the range +0 ≤ i < 232−1.

As all four properties in obj, in the snippet above, are integer indexes by definition, how come they are not listed in numerical order when I call Object.keys?

I see this same order in Chrome, Firefox, Edge, even Internet Explorer 11. It seems like they apply the "ascending numeric index order" for array indexes, not (all) integer indexes. Only that can explain why 1111111111 and 2222222222 are ordered first and in numerical order (the only two keys that are < 232-1), and 4444444444 and 5555555555 are ordered last in their original relative order.

What am I missing? Are these implementations violating the specs?

trincot
  • 317,000
  • 35
  • 244
  • 286
  • i am not that familiar with javascript. array and object are the same thing? as long as they are properties of an object can they be indexes of an array? – Tuckbros Feb 07 '20 at 21:59
  • @Tuckbros, an array is an object with some added behaviour specific for arrays. But even on a plain object (not array), the specification calls some properties *array index*, just based on whether those properties (which really are string keys) represent numbers. It is confusing, yes. – trincot Feb 07 '20 at 22:02
  • 0..0 ok, if u want to see them in numerical order lowest to highest it's quite simple `Object.keys(obj).sort()` if u want to see them from highest to lowest `Object.keys(obj).sort().reverse()` – The Bomb Squad Aug 18 '20 at 21:08
  • Yes, but the question was why they come out in this odd order (consistently). – trincot Aug 18 '20 at 21:10

1 Answers1

4

None of the major implementations had ever been in line with that particular ES6 specification. But note that exceptions were allowed in EcmaScript 2015-2019 (see this)

Concerning the described behaviour, see for instance the V8 bug report Issue 7874: Respect OrdinaryOwnPropertyKeys order.

While EcmaScript 2016, 2017 and 2018 specifications remained unchanged in this respect, it was decided to align EcmaScript2019 with reality. The section on [[OwnPropertyKeys]]() now reads:

  1. For each own property key P of O that is an array index, in ascending numeric index order, do
        a. Add P as the last element of keys.

So reference is to array index, which has an unchanged definition (+0 ≤ i < 232−1).

This change occurred in pull request Normative: Use array indices instead of integer indices in OrdinaryOwnPropertyKeys. See also the comments and cross-references there.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • I have read those parts of the spec probably half a dozen times. Not too long ago, my memory told me "integer index properties", but reading the spec again (i always load the latest), saw "array index properties". I thought i just made a small mistake with the words, but this explains it all. However, i think the order returned by `Object.keys` was still implementation defined in ES2015, up until ES2020, so maybe using a different method may be less ambiguous. – ASDFGerte Feb 07 '20 at 22:20
  • @ASDFGerte, indeed, order is still implementation dependent until EcmaScript2020, but all major implementations agree before that spec. See also [this answer](https://stackoverflow.com/questions/30076219/does-es6-introduce-a-well-defined-order-of-enumeration-for-object-properties/60121411#60121411) – trincot Feb 07 '20 at 22:25
  • 1
    @ASDFGerte—I think the original specification got it right (no order) and that subsequent tinkering has been unhelpful. Defining behaviour based on the difference between an integer index and an array index is a recipe for obscure bugs. It might have been helpful to change the order to the order properties are added, but I'm not part of TC39. ;-) – RobG Feb 07 '20 at 22:27
  • Yes, what i mean is, that people may potentially have thoughts like "well, the order of `Object.keys` is implementation defined, so any order you see is valid", when looking at the question's code. @RobG i am also an advocate of "do not rely on property order, use a `Map` or related if you need an order". – ASDFGerte Feb 07 '20 at 22:29
  • @ASDFGerte—yes, that is still the best advice. :-) – RobG Feb 07 '20 at 22:33