Array.prototype.sort()が数値を文字列として並べ替える理由
比較関数を渡さないsort()は、要素を文字列に変換してUnicodeコードポイント順に並べ替えます。数値の大小とは無関係な結果になります。
なぜエラーが出ないのか
出力: [ 1, 10, 2 ]
(エラーなし)- JavaScriptは何も報告しません。文法として正しいためです
出力: [ 1, 10, 2 ]- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 const scores = [10, 1, 2]; 2 console.log(scores.sort( )); ^
比較関数を渡さないsort()は要素を文字列として比較します。"10"は"2"より辞書順で前に来るため、数値としての順序と食い違います。
直し方: (空) を (a, b) => a - b にします。
パターン2
1 const ids = [5, 25, 100, 1]; 2 console.log(ids.sort( )); ^
文字列として比較すると"100"は"25"より前、"25"は"5"より前に来ます。数値の大小で並べたい場合は必ず比較関数を渡します。
直し方: (空) を (a, b) => a - b にします。
パターン3
1 const deltas = [3, -7, 2, -1]; 2 console.log(deltas.sort( )); ^
負の数を含む場合も文字列比較の影響を受けます。"-1"は"-7"より文字コード順で前に来るため、数値としては逆順になります。
直し方: (空) を (a, b) => a - b にします。
パターン4
1 const values = [40, 5, 200, 1]; 2 console.log(values.sort( )); ^
比較関数を省略すると文字列として並べ替えられます。桁数が揃っていない数値ほどずれが目立ちます。
直し方: (空) を (a, b) => a - b にします。
パターン5
1 const temps = [9, -3, 15, 2]; 2 console.log(temps.sort( )); ^
負の数が混ざっても文字列比較の影響を受けます。数値として並べたい場合は必ず比較関数を渡します。
直し方: (空) を (a, b) => a - b にします。
よくある誤解
「sort()は数の大小で並べ替えてくれるはず」という思い込みは誤りです。既定の比較は文字列としての比較のため、100は"5"より小さい文字列"100"として扱われ、5より前に来てしまいます。
実務での勘所
sort()に比較関数を渡すときの契約は、真偽値ではなく「負・0・正のどれか」を返すことです。(a, b) => a - bと書くと、aがbより小さければ負の値、大きければ正の値、等しければ0になり、これがそのまま昇順の並べ替え指示として機能します。(a, b) => a > bのように真偽値を返す書き方でも多くの実装では動いてしまいますが、これは仕様が保証する契約ではありません。正しい比較関数は常に数値を返すように書くべきです。