← 中文资源

简体中文版本

JavaScript Array.sort — 数字按字符串排序

通过提供数值比较器,修复意外的排序结果——因为 Array.sort 默认把元素转为字符串并按字典序比较。

阅读英文原文

症状

本篇调试指南针对“JavaScript Array.sort — 数字按字符串排序”。内容涵盖可观察的症状、可复现的诊断路径、根本原因、具体修复方式,以及如何验证修复并防止回归。

可观察到的症状包括:

  • [10, 9, 1] 排序后为 [1, 10, 9]
  • 负数排序结果出人意料
  • 按数值键排序对象时顺序错误

诊断

先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。

步骤 1

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

按字典序 “1” < “10” < “9”,解释了该输出。

步骤 2

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

比较器返回数字,恢复数值顺序。

常见诱因(按出现频率排序):

  • 未传比较器调用 sort,元素按字符串比较
  • 比较器返回布尔值而非负/零/正数
  • 排序就地修改原数组,影响后续读取

根因

未提供比较器时,Array.prototype.sort 会把元素转为字符串再比较,因此 “10” 排在 “9” 之前。正确的比较器必须返回负数、零或正数。

修复

数字或对象排序都应传比较器:升序 (a, b) => a - b,降序 (a, b) => b - a,对象按键显式比较。若需保留原顺序,先复制。

注意:sort 就地修改;对共享数组排序会影响其他代码。应使用 toSorted 或 […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);

验证

运行排序并确认数值升序;使用副本时断言原数组未变。

修复后补充一条回归测试,复现原始症状,防止问题再次出现。

这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。