1

JavaScript has set of rules when it comes to order object properties. There is strange example for me.

When timestamp in milliseconds is used as object property key, then ordering doesn't work.

When timestamp in seconds is used as object property key, then ordering works.

var objS = {
    1600333200: 'a',
    1600419600: 'b',
    1600338600: 'c'
};
console.log('seconds', JSON.stringify(objS));


var objMs = {
    1600333200000: 'a',
    1600419600000: 'b',
    1600338600000: 'c'
};
console.log('milliseconds', JSON.stringify(objMs));

Are there any explanation?

poletn23
  • 534
  • 4
  • 17
  • I think numeric keys up ro 2^32 (or 2^31?) come out ordered ... but ... I'd have to look if that's in some specification - I've always been of the opinion that key order is not guaranteed at all - but specs change – Jaromanda X Sep 18 '20 at 11:15
  • AFAIK, The ordering of keys in JS object aren't guaranteed for any type. I strongly suggest you do not rely on them for any kind of logic. – Saurabh Tiwari Sep 18 '20 at 11:16
  • I just read that the order should be numeric for any key that can be an integer up to 2^53 ... but clearly that is wrong – Jaromanda X Sep 18 '20 at 11:19
  • @SaurabhTiwari - there has been a change in ES6 - just hunting it down (that's what google is for) – Jaromanda X Sep 18 '20 at 11:20
  • [Does ES6 introduce a well-defined order of enumeration for object properties?](https://stackoverflow.com/questions/30076219/does-es6-introduce-a-well-defined-order-of-enumeration-for-object-properties) – Andreas Sep 18 '20 at 11:20
  • @SaurabhTiwari - the spec says `"integer indices in ascending numeric, then strings in property creation order, then symbols in property creation order"` - so, there is a specified order ... just the integer thing seems whack – Jaromanda X Sep 18 '20 at 11:21
  • 1
    a quick test ... integer means number up to `2^32` after that they are not considered numeric - so become "strings in creation order" – Jaromanda X Sep 18 '20 at 11:26
  • The millisecond keys should still be treated as integers, `Number.MAX_SAFE_INTEGER < 1600333200000 // false` – Mr. Polywhirl Sep 18 '20 at 11:33
  • Use `Array` instead, and `sort`. `Object` does NOT guarantee order. – iAmOren Sep 18 '20 at 11:42

1 Answers1

0

Traditionally, the order of properties in an object (think of a map) is almost never guaranteed; but since the introduction of ECMAScript 2015 Language Specification, the predictability of property order has been introduced. But… the order of keys is still not guaranteed according to the JSON spec.

You could write your own serialization function to sort the keys numerically.

const serialize = obj =>
  `{${Object.keys(obj)
    .sort((a, b) => parseInt(a) - parseInt(b))
    .map(key => `"${key}":${JSON.stringify(obj[key])}`).join(',')}}`;

var objMs = {
  1600338600000: 'c',
  1600333200000: 'a',
  1600419600000: 'b',
};

console.log('milliseconds', serialize(objMs));

Output

milliseconds {"1600333200000":"a","1600338600000":"c","1600419600000":"b"}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132