3

I recently discovered that arrays are orderable:

>> [1, 2] < [3, 4]
<- true
>> [1, 2] < [0, 4]
<- false

And by the looks of it, it seems that the two arrays are compared element by element, so if the first element in both arrays is equal, then the 2nd elements are compared, etc:

>> [1, 3] > [1, 2]
<- true

However, this assumption doesn't hold true with negative numbers:

>> [-1, 2] < [-2, 2]
<- true
>> -1 < -2
<- false

So, how are arrays actually ordered?

I've read through the Comparison operators docs at MDN, but I couldn't find any relevant information.

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
  • To quote that MDN link: `Each of these operators will call the valueOf() function on each operand before a comparison is made.` I'll have to look up exactly what the `valueOf` method does to arrays, but iirc it makes them into strings and putting commas between each value - and strings are compared lexicographically. I think this explains the behaviour you observe - but I'm not going to put this as an answer because I'm unsure on some of the details. – Robin Zigmond Oct 07 '18 at 10:08
  • @RobinZigmond I checked that - `valueOf` simply returns the original array unchanged. – Aran-Fey Oct 07 '18 at 10:09
  • 2
    Related, if not a dupe of https://stackoverflow.com/questions/8328908/javascript-surprising-array-comparison, though I like the answer given to this one a lot more than the ones in the linked Q/A. – Ilja Everilä Oct 07 '18 at 10:38
  • @IljaEverilä Good find, thanks. – Aran-Fey Oct 07 '18 at 10:40
  • @IljaEverilä Yeah, I agree. I guess I'll leave the decision to the JS folks. – Aran-Fey Oct 07 '18 at 10:42

1 Answers1

7

In comparison, JS converts non-primitive types (array) to primitive types:

For relational abstract comparisons (e.g., <=), the operands are first converted to primitives, then to the same type, before comparison.

Details of this conversion and comparison algorithm can be found here:

Long story short:

  1. On both arrays, ToPrimitive is called with hint = Number.
  2. [[DefaultValue]](Number) tries calling valueOf(), which returns the same array.
  3. As it is still not primitive type, toString() is tried.
  4. It returns "[1,2,3]" string, which is primitive type.
  5. Ok, now we are comparing two strings (no arrays anymore), alphabetically.
Roman Hocke
  • 4,137
  • 1
  • 20
  • 34