Desk Clarity

A field guide to everyday digital problems.

Developer tools / Practical guide

JavaScript Sort Puts 10 Before 2: Use a Numeric Comparator and Choose Mutation

Array sort without a comparator uses string ordering.

By ON Lab2 min readSources checked November 10, 2026 (KST)

Array sort without a comparator uses string ordering. For ordinary finite numbers, provide (a, b) => a - b. Decide separately whether the operation should change the original array.

Reproduce in an empty temporary directory

This isolated example creates only fixture data in its working directory or runs local JavaScript. Run it separately from your project so the named files cannot overwrite real work.

const assert = require('node:assert/strict');
const values = [2, 10, 1];
const textOrder = [...values].sort();
const numericOrder = [...values].sort((a, b) => a - b);
console.log(JSON.stringify({textOrder, numericOrder, original: values}));
assert.deepEqual(textOrder, [1, 10, 2]);
assert.deepEqual(numericOrder, [1, 2, 10]);
assert.deepEqual(values, [2, 10, 1]);

Observed local output

{"textOrder":[1,10,2],"numericOrder":[1,2,10],"original":[2,10,1]}

What to compare

The two sorted copies contain identical inputs in different orders. The original remains unchanged because the fixture copied before sorting. Supplying the comparator fixes ordering; copying fixes ownership. They solve separate problems. An in-place sort can otherwise affect another part of an application that holds the same array reference.

Choose the next action

Validate the input type before choosing the comparator. If numeric text is accepted, parse and reject invalid values through an explicit input policy, then sort the resulting numbers. For records, compare the intended numeric property and add a deliberate secondary key when ties need a specific business order. For strings that represent labels or identifiers, numeric conversion may discard leading zeros or precision and may be the wrong contract.

Limits and verification

The subtraction comparator shown is for suitable Number values. It is not a complete policy for NaN, missing values, mixed types or BigInt values. A comparator must return a number with consistent ordering behavior, not a boolean such as a > b. Modern toSorted can produce a sorted copy directly where supported; the spread-and-sort fixture makes the ownership choice visible without depending on that newer method.

Related: Array Map with parseInt Produces NaN: Stop Passing the Index as the Radix.

Isolated example executed on macOS on November 10, 2026 (KST), using Bash 3.2, Python 3 for the byte fixture, and Node v26.5.0. Results describe the example, not your application or every runtime version.

Sources & further reading