← Debugging Guides

阅读中文版本

JavaScript Array.sort — Numbers Sorted as Strings

Fix unexpected sort order by supplying a numeric comparator, since the default Array.sort converts elements to strings and compares lexicographically.

beginnerdebuggingjavascriptarrayssort

Symptoms

  • [10, 9, 1] sorts to [1, 10, 9]
  • Negative numbers sort in a surprising order
  • Sorting objects by a numeric key gives wrong order

Possible causes

  • sort is called without a comparator, so elements are compared as strings
  • A comparator returns a boolean instead of a negative/zero/positive number
  • Sorting mutates the original array in place, changing later reads

Diagnosis steps

Reproduce the string comparison

node -e "console.log([10,9,1].sort())"

Interpretation

"1" < "10" < "9" lexicographically explains the output.

Use a numeric comparator

console.log([10,9,1].sort((a, b) => a - b))

Interpretation

The comparator returns a number, restoring numeric order.

Root cause

Array.prototype.sort compares by converting elements to strings unless a comparator is given, so "10" precedes "9". A correct comparator must return a negative, zero, or positive number.

Fix

Always pass a comparator for numbers or objects: (a, b) => a - b for ascending, (a, b) => b - a for descending, and compare object fields explicitly. Copy first if the original order must be preserved.

Risk note

sort mutates in place; sorting a shared array can surprise other code. Use toSorted or [...arr].sort.

Verify the fix

Run the sort and confirm ascending numeric order; assert the original array is unchanged when using a copy.

Symptoms

This guide profiles the failure behind “JavaScript Array.sort — Numbers Sorted as Strings”. It walks through the observable symptoms, a reproducible diagnosis path, the underlying root cause, the concrete fix, and how to verify the change and prevent a regression.

Observed symptoms include:

  • [10, 9, 1] sorts to [1, 10, 9]
  • Negative numbers sort in a surprising order
  • Sorting objects by a numeric key gives wrong order

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Reproduce the string comparison

node -e "console.log([10,9,1].sort())"

“1” < “10” < “9” lexicographically explains the output.

Step 2: Use a numeric comparator

console.log([10,9,1].sort((a, b) => a - b))

The comparator returns a number, restoring numeric order.

Likely contributors, in order of frequency:

  • sort is called without a comparator, so elements are compared as strings
  • A comparator returns a boolean instead of a negative/zero/positive number
  • Sorting mutates the original array in place, changing later reads

Root Cause

Array.prototype.sort compares by converting elements to strings unless a comparator is given, so “10” precedes “9”. A correct comparator must return a negative, zero, or positive number.

The Fix

Always pass a comparator for numbers or objects: (a, b) => a - b for ascending, (a, b) => b - a for descending, and compare object fields explicitly. Copy first if the original order must be preserved.

Watch out: sort mutates in place; sorting a shared array can surprise other code. Use toSorted or […arr].sort.

const nums = [10, 9, 1, 100];

// ❌ lexicographic -> [1, 10, 100, 9]
// nums.sort();

// ✅ numeric ascending
console.log([...nums].sort((a, b) => a - b)); // [1, 9, 10, 100]

// objects by key, without mutating the source
const sorted = [...items].sort((a, b) => a.score - b.score);

Verify and Prevent

Run the sort and confirm ascending numeric order; assert the original array is unchanged when using a copy.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.