How does the sort method decide the order of elements?
Sort takes an optional comparison function. If you do not supply one, it compares the elements as strings, which is why sorting numbers without a comparator gives you an obviously wrong result.
The reason is that the default comparison converts both values to strings and compares them character by character. So ten comes before nine, because the string "10" sorts before "9" in character order.
When you do supply a comparator, the contract is simple. The comparator receives two elements and returns a negative number when the first should come before the second, zero when they are equivalent, and a positive number when the first should come after the second. You do not have to return minus one, zero and one; any negative and any positive value work, and returning the difference of the two values is the usual shortcut.
Two properties are worth knowing. Sort is stable in modern engines, meaning that elements the comparator treats as equal keep their original relative order. That matters when you sort by one field and then expect a secondary field to be preserved. And sort mutates the array it is called on, which is why the newer toSorted method is often the safer choice, since it returns a sorted copy instead.