Does .reduce() or .push() order objects automatically?

Hi all!
I’ve come across this MDN example on .reduce() but I don’t understand why the result is an ‘ordered’ group of objects (numbers from lower to higher) if there’s no sorting function whitin the code.
I.e.: values are pushed inside secuentially (21, 30, 20, you can see this uncommenting console.logs in this repl.it) but result is not (20,21,30).
Tyvm!

Objects are not ordered,

{
  1: 'foo'
  2: 'bar'
}

is exactly the same as

{
  2: 'bar'
  1: 'foo'
}

JS Consoles generally print the object keys in order though, it makes it easier to read.

In the example, the result is written

// groupedPeople is:
// { 
//   20: [
//     { name: 'Max', age: 20 }, 
//     { name: 'Jane', age: 20 }
//   ], 
//   21: [{ name: 'Alice', age: 21 }] 
// }

But it could have been written

// groupedPeople is:
// { 
//   21: [{ name: 'Alice', age: 21 }],
//   20: [
//     { name: 'Max', age: 20 }, 
//     { name: 'Jane', age: 20 }
//   ], 

Edit: sorry, I misread. Just what @chuckadams said. Sets retain insertion order though, they never sort the array (how would they know in advance how the programmer wanted the array sorted??)

> t = new Set([2,4,1])
Set { 2, 4, 1 }
> [...t]
[ 2, 4, 1 ]
> u = new Set()
Set {}
> u.add(2)
Set { 2 }
> u.add(4)
Set { 2, 4 }
> u.add(1)
Set { 2, 4, 1 }
> [...u]
[ 2, 4, 1 ]

The ordered array has to do with the “remove duplicate items” example. They’re just showing another way to do it without reduce that involves creating an Array from a Set, which apparently always returns an array with the elements in sorted order. The blurb in the note section has nothing to do with reduce and is just a distraction in otherwise good docs.

Ty guys, I’m not sure I’m getting it though because in the example I was testing on the repl.it, it wasn’t using Set nor any ordering function, just grouping objects.
I’d understand that JS consoles tried to make it more readable but this doesn’t happen when I change numbers for letters so I guess it just leaves it as is just in case when it finds non number values?

Edit: found some info on the topic like this stackoverflow answer that shows similar behavior.

It’s always going to leave it as is, it’s never going to sort the items put into the object because:

  1. Objects don’t really have order. As the SO answer details, most JS engines respect insertion order in the right circumstances, but that’s just an implementation detail; objects having order in some circumstances isn’t a hugely useful thing. In this case isn’t really relevant, the items in that code do not get sorted at all.
  2. It implies the JS engine, without being told, can infer the order that the programmer wants items sorted. Which is not possible.
  3. When the items get put into the arrays in that example, they come out in the order they go in: arrays are very definitely ordered, but again, the JS engine will not automatically sort anything.

It always leaves it as is. Also, how would it sort number values? Sorting lowest -> highest is just as correct as highest -> lowest, and in JS, which compares by string value, 1, 10, 11, 2, 23, 34 is just as correct as 1, 2, 10, 11, 23, 34

1 Like

Ok, so if I’m understanding it correctly arrays just have the order in which elements go in whereas objects do not have any order “per se”, however from what I’ve been able to understand (I hope) from all this and the SO post, the console/output does show keys in a weird order when it encounters numbers.

I’ve modified the repl.it example to check this and the function processes items in order (eg 21 first, 20 second) but shows number keys ordered by amount (20 first, 21 second) even though it pushes the other value types (strings and boolean) as expected.

Console does order the keys, but that will be dependent on what they are, as you say.

As an edit to earlier answer, I wasn’t quite correct, if you get the keys of an object using a relevant piece of JS functionality (which is what I assume most logger implementations will be doing, rather than using custom logic like just for...in-ing over the object), then the keys will be ordered:

  • firstly, any integer keys, in ascending order
  • followed by any non-integer keys in insertion order

I assume it needs to do that because Arrays are objects as well, and have integer keys followed by a length key.

It runs an internal method called OwnPropertyKeys which builds a list of the keys in that order. I think you should be able to verify that by using the getOwnPropertyNames function; the Reflection API methods use that, and I assume the Object.keys function (+ Object.values and Object.entries) does as well

1 Like

Ok, I get it. I’ll study those methods/functions further as they’re beyond my current understanding of JS.
Thank you very much for your time and explanations, :clap: