JavaScript Array Sort Method: Complete Guide
sort() arranges array elements in place. Learn how default string sorting works, how to write a compare function for numbers and objects, and common pitfalls.
sort() arranges the elements of an array in place and returns the sorted array. It seems simple but has a default behavior that surprises nearly every JavaScript beginner: it sorts everything as strings, regardless of whether the values are actually numbers.
const numbers = [3, 1, 10, 2, 20];
numbers.sort();
console.log(numbers); // [1, 10, 2, 20, 3] -- not what you expected!The default sort() converts each element to a string and compares them character by character. The string "10" comes before "2" because "1" is less than "2". This is called lexicographic order.
To sort numbers correctly, you must provide a compare function that tells sort() how to compare two values numerically instead of as text.
The Compare Function
A compare function takes two elements (a and b) and returns a number that tells sort() how to order them:
| Return value | Meaning |
|---|---|
Negative (< 0) | Place a before b |
Zero (0) | Keep the order of a and b unchanged |
Positive (> 0) | Place b before a |
The simplest numeric compare function subtracts one from the other:
const numbers = [3, 1, 10, 2, 20];
// Ascending order (small to large)
numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 2, 3, 10, 20]For descending order, swap the subtraction so larger numbers produce a negative result and sort to the front instead of the back:
numbers.sort((a, b) => b - a);
console.log(numbers); // [20, 10, 3, 2, 1]The compare function is called multiple times during sorting. You do not need to worry about the sorting algorithm -- the engine handles that. You just define the order rule, and the engine applies it consistently across every pair of elements it needs to compare.
Sorting Strings
For strings, the default sort() works for basic alphabetical order:
const fruits = ["banana", "apple", "cherry", "date"];
fruits.sort();
console.log(fruits); // ["apple", "banana", "cherry", "date"]But default sort is case-sensitive. Uppercase letters come before lowercase in string comparison, which can put capitalized words in unexpected positions:
const mixed = ["Banana", "apple", "Cherry", "date"];
mixed.sort();
console.log(mixed); // ["Banana", "Cherry", "apple", "date"]For case-insensitive sorting, use localeCompare() with a sensitivity option that treats uppercase and lowercase letters as equal instead of comparing raw character codes:
mixed.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: "base" }));
console.log(mixed); // ["apple", "Banana", "Cherry", "date"]localeCompare() handles language-specific sorting rules, such as accented characters and locale-specific alphabetical order, and is the right choice for user-facing string sorting.
Sorting Objects by a Property
To sort an array of objects, access the property inside the compare function instead of comparing the objects directly:
const products = [
{ name: "Laptop", price: 999 },
{ name: "Mouse", price: 29 },
{ name: "Monitor", price: 299 },
{ name: "Keyboard", price: 79 }
];
products.sort((a, b) => a.price - b.price);Sorting by price puts the cheapest product first and the most expensive last, matching the ascending order the subtraction produces:
console.log(products.map(p => p.name));
// ["Mouse", "Keyboard", "Monitor", "Laptop"]The same pattern works for string properties, using localeCompare() instead of subtraction since strings cannot be subtracted the way numbers can:
const users = [
{ name: "Carol", age: 30 },
{ name: "Alice", age: 25 },
{ name: "Bob", age: 35 }
];
users.sort((a, b) => a.name.localeCompare(b.name));
console.log(users);
// Alice, Bob, CarolSorting by Multiple Criteria
Chain comparisons to sort by a secondary field when the primary field is equal. Compare the primary field first, and only fall back to the secondary field when that comparison is a tie:
const students = [
{ name: "Alice", grade: "B" },
{ name: "Bob", grade: "A" },
{ name: "Carol", grade: "B" },
{ name: "Dave", grade: "A" }
];The compare function returns the grade comparison immediately when it is non-zero, and only reaches the name comparison when both students share a grade:
students.sort((a, b) => {
const gradeCompare = a.grade.localeCompare(b.grade);
if (gradeCompare !== 0) return gradeCompare;
return a.name.localeCompare(b.name);
});Students with the same grade end up sorted alphabetically by name within that grade group, since the secondary comparison only runs when grades tie:
console.log(students.map(s => `${s.name} (${s.grade})`));
// ["Bob (A)", "Dave (A)", "Alice (B)", "Carol (B)"]sort() Mutates the Original Array
sort() sorts the array in place and returns a reference to that same array, not a new one, which surprises developers used to methods like map():
const original = [3, 1, 2];
const sorted = original.sort((a, b) => a - b);
console.log(original); // [1, 2, 3] (mutated!)
console.log(sorted); // [1, 2, 3] (same array)
console.log(original === sorted); // trueTo sort without mutating, create a copy first with the spread operator, then sort the copy instead of the original:
const original = [3, 1, 2];
const sorted = [...original].sort((a, b) => a - b);
console.log(original); // [3, 1, 2] (unchanged)
console.log(sorted); // [1, 2, 3]This copy-then-sort pattern is worth using by default in any function that receives an array it does not own, since callers rarely expect their data to change. For more on copying arrays, see JS Spread Operator for Arrays.
Sorting Dates
Dates sort correctly with a numeric compare function because JavaScript dates convert to milliseconds when subtracted:
const events = [
{ name: "Conference", date: new Date("2026-08-15") },
{ name: "Workshop", date: new Date("2026-06-01") },
{ name: "Meetup", date: new Date("2026-09-20") }
];
events.sort((a, b) => a.date - b.date);
console.log(events);
// Workshop (June), Conference (August), Meetup (September)Common Mistakes
Using sort() on numbers without a compare function. This silently produces string-order results instead of numeric order, and nothing warns you that it happened:
// Wrong: default string sort
[100, 5, 20, 1].sort(); // [1, 100, 20, 5]
// Right: numeric compare function
[100, 5, 20, 1].sort((a, b) => a - b); // [1, 5, 20, 100]This is the single most common array mistake in JavaScript. Never sort numbers without a compare function, even when the array looks small enough that the bug seems unlikely to matter.
Forgetting that sort() mutates. A function that sorts an argument array silently changes the caller's original data too, which can cause confusing bugs elsewhere:
const data = [3, 1, 2];
function processData(arr) {
arr.sort((a, b) => a - b); // Mutates the caller's array!
return arr;
}
const sorted = processData(data);
console.log(data); // [1, 2, 3] -- original changed!Functions that sort their arguments should either copy first or clearly document that they mutate their input. When in doubt, prefer copying: [...arr].sort(...).
Trying to sort() on an array with mixed types. Without a compare function, everything still gets converted to a string first, even numbers mixed in with text:
const mixed = [1, "hello", 3, "world"];
// sort() works but the result is based on string conversion
mixed.sort();
console.log(mixed); // [1, 3, "hello", "world"] (numbers first, then strings)JavaScript's sort() has been required to be stable since ES2019, meaning equal elements always keep their original relative order. But mixed-type arrays still produce results that are rarely useful. Keep arrays homogeneous when sorting.
Now that you can sort arrays, learn how to remove duplicates from sorted data.
Rune AI
Key Insights
- sort() converts elements to strings by default, so [3, 1, 10] sorts to [1, 10, 3].
- Always provide a compare function for numeric sorting: (a, b) => a - b.
- sort() mutates the original array. Copy first with [...arr] to avoid mutation.
- Return a negative number to place a before b, positive to place b before a, 0 to keep equal.
- For objects, access the property in the compare function: (a, b) => a.price - b.price.
Frequently Asked Questions
Why does sort() put 10 before 2?
Does sort() change the original array?
How do I sort an array of objects by a property?
Conclusion
sort() is powerful but has a surprising default behavior that catches every beginner at least once. The key rule: never use sort() without a compare function for numbers, and always remember it mutates the original array. Once you master the compare function pattern, you can sort anything -- numbers, strings, dates, and complex objects by any property.
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.