Object.entries(), why is my array sorted numerically by default?

Viewed 219

I was writing a simple code exercise solution and came across what appears to be object.entries() doing an internal numeric ascending sort. I was expecting to have to sort the key value pairs myself since the docs say that you must do a sort if you need a specific order. Why is this is happening and can I rely on this behavior?

/*
Given an input of [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20], 
make a function that organizes these into individual array that is ordered. 
The above input should return:
[[1,1,1,1],[2,2,2],4,5,10,[20,20],391,392,591].
*/
const cleanTheRoom = (mess) => { 
  let hash = {};
  for (let i = 0; i < mess.length; i++) {
    (hash.hasOwnProperty(mess[i])) ? hash[mess[i]]++ : hash[mess[i]] = 1;
  }
  const clean = [];
  for (const [key, value] of Object.entries(hash)) {
    (value > 1) ? clean.push(Array(value).fill(key)) : clean.push(key);
  }
  return clean;
}

let cleaned = cleanTheRoom(
  [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20]
);

console.log(cleaned);

2 Answers

Object.entries uses the spec operation EnumerableOwnPropertyKeys, which in turn uses the object's [[OwnPropertyKeys]], which for most objects (including arrays) is OrdinaryOwnPropertyKeys. That operation specifically special-cases property names that look like array indexes and lists them in numeric order. The algorithm is:

  1. Let keys be a new empty List.
  2. For each own property key P of O such that P is an array index, in ascending numeric index order, do
    1. Add P as the last element of keys.
  3. For each own property key P of O such that Type(P) is String and P is not an array index, in ascending chronological order of property creation, do
    1. Add P as the last element of keys.
  4. For each own property key P of O such that Type(P) is Symbol, in ascending chronological order of property creation, do
    1. Add P as the last element of keys.
  5. Return keys.

That's because Objects are meant to work as hashes on JavaScript, and in any implementation, hashes shouldn't be used to store insert-ordered values.

The main usage behind Object.entries is when you want to retrieve the keys/values of a specific Object without a specific order on either keys or values.

Related