So when I try to sort alphabets with just sort, it works as expected like:
['a', 'A'].sort().join('') // 'Aa'
However, when I use localeCompare with sort, it doesn't work as expected:
['a', 'A'].sort((a, b) => a.localeCompare(b)).join('') // 'aA'
OR
['a', 'b', 'A', 'c', 'b', 'A', 'B'].sort((a, b) => a.localeCompare(b)).join('')
// 'aAAbbBc'
Why doesn't the sort place uppercase letters like 'A' before lowercase case letters as would have happened when using just sort() with no arguments ? I'm trying to sort the letters in ascending order (lexicographically).Thanks!
The two are indeed not guaranteed to use the same algorithm for string comparison:
ECMAScript on localeCompare has:
The two Strings are compared in an implementation-defined fashion.
[...]
This function is intended to rely on whatever language-sensitive comparison functionality is available to the ECMAScript environment from the host environment, and to compare according to the rules of the host environment's current locale.
ECMAScript on sort on the other hand has this step in its procedure:
Let xSmaller be ! IsLessThan(xString, yString, true).
isLessThan is defines the comparison in specific terms (referring to code points), and it is the same procedure that is used for determining whether a < b.
This should explain why there can be a difference.
If you are looking for a sort callback function that will have the same effect as when you would not have provided one, then go for this one:
let cmp = (a, b) => (String(a) > String(b)) - (String(a) < String(b));
// Demo
let arr = ['a', 'A', undefined, 4, NaN, Infinity, null];
let sorted1 = [...arr].sort(cmp);
let sorted2 = [...arr].sort();
console.log(sorted1);
console.log(sorted2);