What you'll be able to do
By the end of this page you should be able to sort strings, sort numbers with a compare function, remember that sort mutates the original array, and avoid the classic [10, 2, 1] → [1, 10, 2] surprise.
Previous post: slice, splice, concat.
Who this is for
- People who call
numbers.sort()and get a strange order - Beginners who lose the original order because
sortedited in place - Anyone sorting prices or scores for a UI list
You can skip this if you already pass (a, b) => a - b for numbers and copy with slice before sorting when needed. Come back when a “sorted” column looks alphabetical instead of numeric.
Default sort: as strings
With no compare function, items are converted to strings and ordered lexicographically (dictionary order).
const nums = [10, 2, 1];
nums.sort();
console.log(nums); // [1, 10, 2] — string order
Scenario A — scores on a quiz. Broken until you add a numeric compare.
Scenario B — names. Default sort is often fine: ["Ben", "Asha"].sort().
Numbers: pass a compare function
The compare function should return a negative number if a should come before b, positive if after, and 0 if equal.
const nums = [10, 2, 1];
nums.sort(function (a, b) {
return a - b; // ascending
});
console.log(nums); // [1, 2, 10]
const desc = [10, 2, 1].sort(function (a, b) {
return b - a;
});
console.log(desc); // [10, 2, 1]
Scenario A — price low to high. a - b.
Scenario B — newest first when you store timestamps as numbers. b - a.
sort mutates — copy when you need the original
const original = [3, 1, 2];
const sorted = original.slice().sort(function (a, b) {
return a - b;
});
console.log(original); // [3, 1, 2]
console.log(sorted); // [1, 2, 3]
Scenario A — keep “upload order” and show “sorted view.” Sort a copy.
Scenario B — one-off script where mutation is fine. Sorting in place is OK if nothing else points at the old order.
Sorting objects by a field
const posts = [
{ title: "B", views: 3 },
{ title: "A", views: 10 },
];
posts.sort(function (a, b) {
return b.views - a.views;
});
Scenario A — leaderboard. Sort by views descending.
Scenario B — alphabetical titles. Compare strings with a.title.localeCompare(b.title) when you need reliable text order.
A tiny practice file
Save as sort.html.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>sort</title>
</head>
<body>
<button id="bad">Default sort [10,2,1]</button>
<button id="good">Numeric sort copy</button>
<pre id="out"></pre>
<script>
const out = document.getElementById("out");
document.getElementById("bad").addEventListener("click", function () {
const nums = [10, 2, 1];
nums.sort();
out.textContent = "default: " + JSON.stringify(nums);
});
document.getElementById("good").addEventListener("click", function () {
const original = [10, 2, 1];
const sorted = original.slice().sort(function (a, b) {
return a - b;
});
out.textContent =
"original: " + JSON.stringify(original) + "\n" +
"sorted: " + JSON.stringify(sorted);
});
</script>
</body>
</html>
Mistakes I see a lot
1. Number sort without a compare function. Lexicographic order.
2. Forgetting mutation. Shared arrays reorder under other code.
3. Returning booleans from compare. Use a number (a - b), not a > b alone (works in some engines inconsistently for sort contracts).
4. Sorting mixed types casually. Convert or normalize first.
5. Comparing strings with -. Prefer localeCompare for text.
6. Stable-order assumptions across all old environments. For beginners, focus on compare + copy; advanced stability comes later.
What to try before the next post
- Reproduce
[10,2,1].sort(). - Fix it with
a - b. - Sort a copy; prove the original is unchanged.
- Build the tiny HTML file.
Next in this series: common array patterns — everyday combinations so you stop reinventing loops.
Try this next outside the series
Arrays get easier when you see them render UI lists and move through real transforms.
- React hooks patterns — see arrays, mapping, and derived state inside everyday React code
- JSON Formatter — inspect array payloads from APIs without losing the shape