jashkenas/underscore — pull request #1821 by dohse (2014-09-01 21:55:50+00:00)
Title: Make sortBy() behave more like native array sort

According to the ECMA Script specification for sort [1] an Array is
sorted according to the string representation of its values. sortBy()
compares the values with the less-than and greater-than operators. This
causes undefined orders in phantomjs like these:

_.sortBy([1, NaN]) // => [1, NaN]
_.sortBy([NaN, 1]) // => [NaN, 1]

but also to to real pathological results in Firefox, Chrome and V8 in
general like this:

_.sortBy([2, NaN, 1]) // => [2, NaN, 1]

where the result is not ordered at all.

This fix addresses these issues by ordering all numbers first and
comparing all other values as strings.

This will break all users that assume that numbers will be ordered
alongside with numbers. Unfortunately that ordering is not well defined
(Example V8):

_.sortBy(['9', 10, '10']) // => [ '9', 10, '10' ]
_.sortBy([10, '10', '9']) // => [ 10, '10', '9' ]

With this patch sortBy() returns these results:

_.sortBy([1, NaN]) // => [1, NaN]
_.sortBy([NaN, 1]) // => [1, NaN]

_.sortBy([2, NaN, 1]) // => [1, 2, NaN]

_.sortBy(['9', 10, '10']) // => [ 10, '10', '9']
_.sortBy([10, '10', '9']) // => [ 10, '10', '9' ]

[1] http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.11