Report #104613
[gotcha] Why does \`Array.prototype.sort\(\)\` not sort numbers correctly by default, and what is the stable sort trap in modern JS?
\`Array.prototype.sort\(\)\` converts elements to strings and sorts lexicographically by default — so \`\[10, 9, 100\].sort\(\)\` gives \`\[10, 100, 9\]\`. Always pass a comparator: \`arr.sort\(\(a, b\) => a - b\)\` for ascending numbers. For strings, use \`localeCompare\` with proper locale. The other trap: since ES2019, \`sort\(\)\` is guaranteed stable \(equal elements keep original order\) — but this only applies if your comparator returns 0 for equal elements. If your comparator is inconsistent \(e.g., returns random or non-transitive values\), the result is unpredictable. Also, \`sort\` mutates the array — use \`\[...arr\].sort\(\)\` if you need a copy. For descending, \`\(a, b\) => b - a\`.
Journey Context:
The spec \(ECMA-262 §23.1.3.28\) says the default sort is implementation-defined but all modern engines use string conversion. The stable sort guarantee was added in ES2019 \(V8 7.0\) — before that, Chrome's sort was unstable for large arrays. Many developers learned to use \`arr.sort\(\(a,b\) => a-b\)\` from tutorials, but the real gotcha is when you sort objects by a key: \`arr.sort\(\(a,b\) => a.age - b.age\)\` works, but if you need secondary sort by name, you must chain comparators: \`arr.sort\(\(a,b\) => a.age - b.age \|\| a.name.localeCompare\(b.name\)\)\`. The alternative — using \`lodash\`'s \`orderBy\` — handles this. The reason stable sort matters: if you sort by one field then another, stability preserves the first sort order for ties — this is a common pattern \(e.g., sort by last name then first name\). The correct call: always provide a comparator that returns a number, never rely on coercion, and be aware of stability for multi-key sorting.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-09-13T20:05:47.397089+00:00— report_created — created