Overview
When you sort an array using the default sort method, lists containing a mix of uppercase and lowercase English words often result in an unexpected order. For example, “Zebra” might appear before “apple.” This happens because computers determine the order based on character codes like ASCII. To sort strings in a natural dictionary order that humans use, you should employ the localeCompare method. This article demonstrates how to correctly sort a list of names or locations using this method to handle case sensitivity and natural language rules.
Specifications
localeCompare Method
This method compares a reference string with a given string and returns a numeric value representing the sort order.
| Method | Meaning | Return Value | Behavior in sort |
| strA.localeCompare(strB) | Compares strA and strB in dictionary order. | Negative (-1) | Places strA before strB |
| Positive (1) | Places strA after strB | ||
| 0 | No change in order |
- Input: The string to be compared.
- Output: A numeric value (-1, 0, or 1) indicating the sort order.
Basic Usage
Difference Between Default sort and localeCompare
By default, uppercase letters (A-Z) take priority over lowercase letters (a-z). Using localeCompare ignores this technical priority and follows the actual alphabetical order.
const members = ['mori', 'Hayashi', 'kogi'];
// 1. Default sort (Uppercase takes priority)
members.sort();
console.log(members);
// ["Hayashi", "kogi", "mori"] - "H" comes before "k" in character codes
// 2. Using localeCompare (Dictionary order)
members.sort((a, b) => a.localeCompare(b));
console.log(members);
// ["Hayashi", "kogi", "mori"] - Alphabetical A->Z regardless of case
Full Code (HTML / JAVASCRIPT)
This demo manages a list of location names. Even if the input data has inconsistent capitalization, the system sorts them correctly in alphabetical order.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Location List Sort</title>
<style>
.sort-panel {
font-family: 'Segoe UI', sans-serif;
max-width: 500px;
padding: 20px;
border: 1px solid #ccc;
border-radius: 8px;
background-color: #f9f9f9;
}
.btn-group {
margin-bottom: 15px;
display: flex;
gap: 10px;
}
button {
padding: 10px 15px;
cursor: pointer;
border: 1px solid #999;
background-color: #fff;
border-radius: 4px;
}
button:hover { background-color: #eee; }
.list-area {
background: white;
border: 1px solid #ddd;
padding: 10px;
min-height: 100px;
}
ul { margin: 0; padding-left: 20px; }
li { padding: 4px 0; border-bottom: 1px dashed #eee; }
.note { font-size: 0.85rem; color: #666; margin-bottom: 10px; }
</style>
</head>
<body>
<div class="sort-panel">
<h3>Location Name Sorting</h3>
<p class="note">Data: ['mori', 'Hayashi', 'kogi', 'Oki', 'nakabayashi']</p>
<div class="btn-group">
<button id="btn-default">Default Sort (ASCII)</button>
<button id="btn-locale">localeCompare (Dictionary)</button>
</div>
<div class="list-area">
<ul id="location-list">
</ul>
</div>
</div>
<script src="location_sort.js"></script>
</body>
</html>
JavaScript
/**
* Location Sorting Script
* Comparing logic differences for string arrays
*/
// 1. Data to be sorted
// Intentionally mixing uppercase and lowercase
let locations = ['mori', 'Hayashi', 'kogi', 'Oki', 'nakabayashi'];
// DOM elements
const listElement = document.getElementById('location-list');
const btnDefault = document.getElementById('btn-default');
const btnLocale = document.getElementById('btn-locale');
/**
* Function to render the list
*/
const renderList = () => {
listElement.innerHTML = '';
locations.forEach(loc => {
const li = document.createElement('li');
li.textContent = loc;
listElement.appendChild(li);
});
};
/**
* Default sorting (Character code order)
* Uppercase (A-Z) comes before lowercase (a-z)
*/
const sortDefault = () => {
locations.sort();
renderList();
};
/**
* Sorting using localeCompare (Dictionary order)
* Alphabetical order without case sensitivity
*/
const sortLocale = () => {
locations.sort((a, b) => {
// Compare using natural language rules
return a.localeCompare(b);
});
renderList();
};
// Initial display
renderList();
// Event settings
btnDefault.addEventListener('click', sortDefault);
btnLocale.addEventListener('click', sortLocale);
Custom Points
When sorting Japanese text, you should specify ‘ja’ as the locale code in the second argument to ensure correct handling of hiragana, katakana, and kanji. For example, list.sort((a, b) => a.localeCompare(b, 'ja')). Note that it cannot determine the specific reading of kanji, so phonetic data is required for perfect results. If you need to sort strings containing numbers, such as “File1” and “File10,” you can enable numeric sorting by passing an options object as the third argument like a.localeCompare(b, undefined, { numeric: true }).
Important Notes
While localeCompare is highly functional, it can be slower than simple comparison operators when sorting extremely large datasets of tens of thousands of items. For most common lists, the performance difference is negligible, but keep this in mind for critical performance scenarios. Additionally, since this involves the sort method, it modifies the original array directly. If you need to keep the original data, create a copy first using the spread syntax like [...locations].sort().
Advanced Usage
Sorting in Descending Order
To reverse the order, simply swap the reference string and the argument in the localeCompare call.
// Ascending (A -> Z)
locations.sort((a, b) => a.localeCompare(b));
// Descending (Z -> A)
locations.sort((a, b) => b.localeCompare(a));
Summary
You should always use the localeCompare method when arranging text data like user names or product titles in a way that is easy for humans to read. The default sort method follows computer-centric logic where uppercase letters take precedence, which can feel unnatural in a UI. Choosing the human-friendly dictionary order with localeCompare is a primary step toward building a more intuitive and user-friendly interface.
