Having all three cases (a < b, a = b, a > b) allows you to have a Total Ordering. But if you specify just one case – just a < b, you end up with a Weak Ordering. The difference is rooted with Mathematics – but to simplify things: with former scheme, you do care about how to order elements that tie with each other, and with the latter scheme, you don't necessarily care.
var list = [
{ age: 65, name: 'Tony'},
{ age: 24, name: 'Joe'},
{ age: 24, name: 'Susan' } // Joe and Susan are tied,
{ age: 5, name: 'Alice'},
];
Suppose we sort the above list of employees by their age. With a total order, we are guaranteed to have the order: Alice, Joe, Susan, Tony. So although Joe and Susan have the same age, their relative order is preserved after the sort. With a Weak ordering however, we will have Alice first and Tony last, but the order of Joe and Susan is left open for choosing. These employees have the same age and so are tied (equal). That's bad for weak orderings as weak orderings don't specify how to order ties in the result – it's ambiguous! So with a weak ordering: we may end up with the result: Alice, Susan, Joe, Tony. When a sorting algorithm preserves the order of ties, we say it is a stable sort.
If your sorting function is like Arrays.prototype.sort() and expects a total ordering, you should always provide all three cases! If you don't do this: 1. tied elements may not be sorted correctly, 2. the browser may be confused and sorting algorithm may fail to correctly sort all the elements (even when there aren't any ties!).
// (*) Array.prototype.sort expects total ordering
// ... so three cases needed
sort(list, function(a, b) { // (*)
if (a.age < b.age) return -1;
if (a.age > b.age) return 1;
return 0;
});
You would only provide one case if the sorting function you're using is expecting a weak ordering. The C++ Standard Library gives a perfect example of a function that expects a weak ordering.
// (*) C++ STL uses weak orderings ...
// ... so only one case needed
struct Employee { int age; string name };
vector<Employee> employees = {
{ 65, "Tony" },
{ 24, "Joe" },
{ 24, "Susan" },
{ 5, "Alice" }
};
struct Sorter {
bool operator()(const Employee &e1, const Employee &e2) const {
return e1.age < e2.age; // (*)
}
};
sort(employees.begin(), employees.end(), Sorter());
Here, you just need to provide just one case a < b in the sorting function. When you sort the elements and there is a tie, it is left open as to how the tied elements should be arranged. From C++ Reference for sort:
comp
... The value returned indicates whether the element passed as first argument is considered to go before the second in the specific strict weak ordering it defines ... Equivalent elements are not guaranteed to keep their original relative order
It turns out the original designer of the C++ Standard Library, Alexander Stepanov, perhaps did not want to use weak orderings and would've preferred to use total orderings (like Javascript!) – probably in order to prevent these ambiguities with ties. In fact many other languages (including Java and Python) use total orderings for their sorting functions. Total orderings are great because they remove ambiguity, so you should make the effect to provide all three cases.