症状
本篇调试指南针对“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);
验证
运行排序并确认数值升序;使用副本时断言原数组未变。
修复后补充一条回归测试,复现原始症状,防止问题再次出现。
这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。