Hacker News new | ask | show | jobs
by PaulJulius 3135 days ago
The new implementation is still wrong, according to the specification.

Array.prototype.sort does not sort an array of numbers as expected. In JavaScript, [2, 10].sort() results in the array [10, 2].

As MDN points out, "The default sort order is according to string Unicode code points... If [compareFn is] omitted, the array is sorted according to each character's Unicode code point value, according to the string conversion of each element." [0] It has an example showing off the unintuitive behavior right at the top of the page.

This behavior is intended per the original ECMAScript specification[1, pg. 68]:

  When the SortCompare operator is called with two arguments 
  x and y, the following steps are taken:
  1. If x and y are both undefined, return +0.
  2. If x is undefined, return 1.
  3. If y is undefined, return −1.
  4. If the argument comparefn was not provided in the call 
     to sort, go to step 7.
  5. Call comparefn with arguments x and y.
  6. Return Result(5).
  7. Call ToString(x).
  8. Call ToString(y).
  9. If Result(7) < Result(8), return −1.
  10. If Result(7) > Result(8), return 1.
  11. Return +0.
The key points are items 4, 7 and 8.

[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

[1] http://www.ecma-international.org/publications/files/ECMA-ST...

2 comments

Isn't that a separate issue? The article was pointing out that [5, 4, 1, 5] was sorted as [4, 1, 5, 5], which is wrong no matter if you're sorting numbers or strings. The bug was the algorithm taking one step too few and the fix was reducing the end trigger by one, which has no effect on what sort order is used. I'm seeing an actual bug that was actually fixed, and any breaks from the spec -- real though they might be -- are better brought up to the maintainers themselves than posted on something only tangently related.
What an awful gem of surprising by design.

Definitely going to add this to my contempt for javascript list.

It's the worst option except for all the others, I think. JS arrays can contain anything, so if the default behavior was to compare elements as numbers, sorting an array containing mixed types would have unpredictable results (because of comparisons to NaN, etc).

Naturally things are only weird for untyped arrays - calling sort() on e.g. an Int32Array does what you'd expect.

Python throws an exception for incomparable types. I guess that's not really practical on the web.
why is it better to silently fail than to throw an exception simply because it's running on a web browser?