Suggest an editImprove this articleRefine the answer for “Sorting an array of numbers”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Always pass a compare function: `arr.sort((a, b) => a - b)` for ascending and `arr.sort((a, b) => b - a)` for descending. Without a comparator `sort()` converts elements to strings and sorts them lexicographically, which turns `[10, 1, 3, 20]` into `[1, 10, 20, 3]`. The comparator must return a negative number when `a` comes first, a positive number when `b` comes first, and zero when the order does not matter. `sort()` mutates the array and returns that same array, so when you need the original untouched, sort a copy: `[...arr].sort((a, b) => a - b)` or `arr.toSorted((a, b) => a - b)`.** ```javascript const numbers = [10, 1, 3, 20]; numbers.sort(); // [1, 10, 20, 3] wrong: string order numbers.sort((a, b) => a - b); // [1, 3, 10, 20] correct ``` **Key point:** `sort()` sorts as strings by default, so for numbers the `(a, b) => a - b` comparator is mandatory.Shown above the full answer for quick recall.Answer (EN)Image**To sort numbers in ascending order, call `sort()` with a compare function: `arr.sort((a, b) => a - b)`.** Without a comparator the method converts elements to strings and lines them up alphabetically, which puts `10` before `3`, and that is the single most common mistake in interviews. ## Theory ### TL;DR - Ascending: `arr.sort((a, b) => a - b)`. - Descending: `arr.sort((a, b) => b - a)`. - With no comparator, `sort()` compares the **string** form of the elements. - The comparator returns a negative number, a positive number or zero, and that defines the order. - `sort()` mutates the source array and returns a reference to it. - Non mutating options: `[...arr].sort(cmp)` or `arr.toSorted(cmp)` (ES2023). ### Quick example ```javascript const numbers = [10, 1, 3, 20]; numbers.sort((a, b) => a - b); console.log(numbers); // [1, 3, 10, 20] ``` ### The beginner mistake: sort() with no comparator ```javascript const numbers = [10, 1, 3, 20]; numbers.sort(); console.log(numbers); // [1, 10, 20, 3], string sorting ``` By default `sort()` converts elements to strings and orders them **lexicographically**, character by character using UTF-16 code units. That is why `"10"` comes before `"2"`: the first character `"1"` is smaller than `"2"`, and the remaining digits never get looked at. One detail worth knowing: the array itself does not become an array of strings, the numbers stay numbers. Only the comparison keys are stringified, so the console shows numbers that are simply arranged "alphabetically". ### The correct way: a compare function ```javascript const numbers = [10, 1, 3, 20]; numbers.sort((a, b) => a - b); console.log(numbers); // [1, 3, 10, 20] ``` The `(a, b) => a - b` function tells the engine **how to compare numbers**: - if `a - b` is less than 0, `a` goes first; - if `a - b` is greater than 0, `b` goes first; - if `a - b` equals 0, the order stays as it was. | Comparator value | What it means | | --- | --- | | Negative | put `a` before `b` | | Positive | put `b` before `a` | | Zero | the elements are equal, the order is preserved | Since ES2019 `sort()` is **stable**: elements for which the comparator returned zero keep their original relative order. That lets you sort in several passes, for example by name first and then by age. ### Descending order and sorting without mutation Descending order is the same comparator the other way round: ```javascript const numbers = [1, 3, 10, 20]; numbers.sort((a, b) => b - a); console.log(numbers); // [20, 10, 3, 1] ``` If the original array must stay intact, sort a copy: ```javascript const arr = [5, 2, 9, 1]; const sorted = [...arr].sort((a, b) => a - b); console.log(sorted); // [1, 2, 5, 9] console.log(arr); // [5, 2, 9, 1], the original is untouched ``` Modern engines ship a ready made non mutating method: ```javascript const sorted = arr.toSorted((a, b) => a - b); // ES2023, returns a new array ``` This matters a lot in React and similar libraries: `state.items.sort(...)` changes the same object, the reference does not change, and no re-render happens. ### Neighbouring cases: strings and objects The same principle covers any data, only the comparator changes: ```javascript // numbers as strings: convert before comparing ['10', '9', '2'].sort((a, b) => Number(a) - Number(b)); // ['2', '9', '10'] // text with correct alphabetical order ['apple', 'Banana', 'cherry'].sort((a, b) => a.localeCompare(b, 'en')); // objects by field const users = [{ name: 'Bob', age: 31 }, { name: 'Alice', age: 25 }]; users.sort((a, b) => a.age - b.age); // Alice first ``` For huge values that do not fit into `Number`, subtraction either returns a `BigInt` or loses precision, so there you write an explicit comparison: ```javascript arr.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)); ``` ### In brief | Task | Code | Result | | --- | --- | --- | | Ascending | `arr.sort((a, b) => a - b)` | `[1, 2, 3, 4]` | | Descending | `arr.sort((a, b) => b - a)` | `[4, 3, 2, 1]` | | Without changing the source array | `[...arr].sort(...)` | a new sorted array | | Without changing it, modern syntax | `arr.toSorted(...)` | a new sorted array | > **Summary:** to sort numbers in ascending order, always pass a compare function: `arr.sort((a, b) => a - b)`. ### Common mistakes - **Calling `sort()` with no arguments on numbers.** That is lexicographic sorting, and on any array mixing one digit and two digit numbers the result is almost always wrong. - **Returning `true` or `false` from the comparator.** For example `arr.sort((a, b) => a > b)`: a boolean coerces to 1 or 0, the engine never receives "less than", and the order becomes unpredictable. A comparator must return a signed number. - **Forgetting that `sort()` mutates.** It changes the source array and returns that same array, not a copy. For data you do not own, props and state, copy first. - **Sorting an array that contains `NaN`.** Any subtraction with `NaN` yields `NaN`, so the comparator effectively answers "unknown" and the order becomes garbage. Filter such values out beforehand. - **Ignoring `undefined` and holes.** `undefined` values always end up at the end, empty slots of a sparse array go even further, and the comparator is never called for them. - **Comparing text with `a - b` or `a > b`.** For strings with non ASCII letters, the correct order comes from `localeCompare` with the right locale.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.