When you sort an array of strings in JavaScript using the default Array.prototype.sort() method, it performs a case-sensitive sort based on Unicode code points. This leads to the unintuitive result where all uppercase letters come before all lowercase letters (e.g., 'Z' comes before 'a').
To achieve a natural, case-insensitive alphabetical sort, you must provide a custom comparison function to the sort() method that uses String.prototype.localeCompare().
The Core Problem: Default Sort is Case-Sensitive
The default sort() method does not produce a natural alphabetical order when dealing with mixed-case strings.
Example of problem:
// Problem: The default sort is not what we want.
let letters = ['Z', 'c', 'a', 'B'];
letters.sort();
console.log(letters); // Output: ['B', 'Z', 'a', 'c']
// Uppercase letters are grouped before lowercase letters.The Solution (Recommended): sort() with localeCompare()
The String.prototype.localeCompare() method is the standard, modern, and most robust way to compare strings according to locale-specific rules. It has built-in options to handle case sensitivity.
By providing a comparison function to sort() that uses localeCompare(), we can achieve a natural, case-insensitive sort.
let letters = ['Z', 'c', 'a', 'B'];
letters.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }));
console.log(letters); // Output: ['a', 'B', 'c', 'Z']How localeCompare() Works for Case-Insensitive Sorting
The a.localeCompare(b, locales, options) method is designed for sophisticated string comparison. The key for our use case is the options object.
sensitivity: 'base': This is the crucial option. It tellslocaleCompareto only consider differences in the base letters. It ignores differences in case ('a'is treated as equal to'A') and accents ('a'is treated as equal to'á').
The localeCompare() method returns a number that the sort() method can use to determine the order:
- Negative:
ashould come beforeb. - Positive:
bshould come beforea. - Zero:
aandbare equal for sorting purposes.
This return value is perfectly compatible with the sort() method's requirements, making localeCompare the ideal tool.
A Note on Mutability (Creating a Copy First)
The Array.prototype.sort() method sorts an array in place, meaning it mutates (modifies) the original array. This can lead to unexpected bugs if other parts of your code rely on the original order.
Conclusion
To achieve a natural, case-insensitive sort of a string array, the default sort() method is not enough.
- The recommended best practice is to provide a custom comparison function to
sort()that uses thelocaleCompare()method with thesensitivity: 'base'option:myArray.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' })); - Always create a copy of your array (e.g., with
[...arr]) before sorting if you want to avoid mutating the original data.