Array.prototype.sort() と toSorted()

sort() は比較関数を渡さないと文字列として並べます。比較関数が返すべき値、真偽値を返すと並ばない理由、undefined と穴の位置、安定ソートの保証までを実行して確かめます。

実行して検証済み処理系Node 22.22.3対応ES1難易度●●○○○目安9更新

sort() は配列を並べ替えます。元の配列を書き換え、同じ配列を返します。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 1, 2, 3 ] true
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 1, 10, 100, 9 ] [ 1, 9, 10, 100 ]

戻り値は新しい配列ではありません元と同じものです。

比較関数を渡さないと文字列になる

引数を省くと、要素を文字列に変えてから並べます。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 10, 'a', false, null, true ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 3, 2, 1 ] [ 3, 1, 2 ]

'10' < '9' なので、109より前に来ます。 数値を並べるときは、必ず比較関数を渡してください。

型が混ざっていても同じです。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 1, 2, 3 ] [ 3, 1, 2 ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 1, 2, 3 ] [ 3, 1, 2 ]

'10' < 'a' < 'false' < 'null' < 'true' の順です。 中身が何であれ、文字列として比べられます。

配列を数値の大きさで並び替える

比較関数が返すべきもの

compare(a, b)数値を返します。

戻り値 意味
負の数 a を前に
0 順番を変えない
正の数 b を前に

だから a - b で昇順、b - a で降順になります。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 3, 2, 1 ] [ 1, 2, 3 ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 'B', 'D', 'A', 'C' ]

常に0を返せば、何も動きません。

元を変えたくないなら

toSorted() は新しい配列を返します(ES2023)。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ '1y', '1z', '2a', '2b' ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 1, 3, undefined ] [ 1, 3, <1 empty item> ]

古い環境では、複製してから並べます。

javascript
const nums = [5, 3, 9, 1, 7, 2, 8];

console.log(nums.sort((a, b) => a > b));
[ 5, 3, 9, 1, 7, 2, 8 ]
javascript
console.log(['い', 'あ', 'う'].sort((a, b) => a - b));
[ 'い', 'あ', 'う' ]

toSorted() は Node 20 / Chrome 110 / Safari 16 より前では使えません。

reverse() も同じく破壊的で、toReversed() が対になります。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 'あ', 'い', 'う' ] [ 'Apple', 'banana', 'cherry' ]
javascript
const original = [3, 1, 2];
const sorted = original.sort((a, b) => a - b);

console.log(original);
[ 1, 2, 3 ]

同じ値の順番は保たれる

sort()安定ソートです(ES2019 以降、仕様で保証されています)。 比較で同じと判定された要素は、元の順番のままになります。

group1BD2ACそれぞれ元の並び順が保たれています。

だから「まず名前順、次に点数順」のような並べ替えは、逆の順に2回かけても作れます。 ただし、1回で書くほうが読みやすくなります。

||左が 0 のときだけ右を見ます同点のときの2番目の基準を、そのまま書けます。

undefined と穴は必ず最後

undefined比較関数に渡されません。無条件で末尾へ回されます。 はさらにその後ろです。

比較関数の中で undefined を気にする必要はありません。 来ないからです。

よくある間違い

比較関数が真偽値を返している

まったく並んでいません。

a > btrue / false を返します。数値に直すと10で、 b を前に」と「変えない」しか表せません。a を前に」(負の数)が作れないので、並べ替えが成立しません。

要素数が少ないと、たまたま並ぶことがあります。だから見逃されがちです。 a - b を使ってください。

文字列を a - b で比べる

文字列の引き算は NaN です。NaN0と同じ扱いになるので、何も起きません。

文字列は既定の並べ替えか、localeCompare() を使います。

文字を正しく数える

並べ替えたつもりで元が変わっている

sorted を作ったつもりでも、original も並び替わっています。同じ配列だからです。 元を残したいなら toSorted()[...original].sort() を使ってください。

まとめ

  • sort()元を書き換える。戻り値は同じ配列
  • 比較関数を省くと文字列として並ぶ。数値には必ず渡す
  • 比較関数は数値を返す。真偽値では並ばない
  • undefinedは比較関数に渡されず、必ず末尾
  • 安定ソートが保証されている。同点は元の順のまま
  • 元を残すなら toSorted()[...arr].sort()

この記事の根拠

  1. Array.prototype.sort — ECMAScript® 2026 Language Specificationtc39.es
  2. Array.prototype.toSorted — ECMAScript® 2026 Language Specificationtc39.es
  3. String.prototype.localeCompare — MDNdeveloper.mozilla.org

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)