Array.prototype.sort() 默认按字符串 Unicode 码点排序,数字数组需传入比较函数如 (a, b) => a - b;对象数组按字段排序需提取值并处理空值和大小写;sort() 原地修改且自 ES2019 起保证稳定排序。

JavaScript 的 Array.prototype.sort() 方法默认按字符串 Unicode 码点排序,**直接调用 arr.sort() 对数字数组排序会出错**——这是最常踩的坑。
为什么 sort() 默认不按数值排序?
因为 sort() 内部把所有元素先转成字符串再比较。比如 [10, 2, 33] 会被当作 ['10', '2', '33'] 排序,结果是 [10, 2, 33]('10' [2, 10, 33]。
只有传入比较函数才能控制逻辑:
- 返回负数 → 第一个参数排在前面
- 返回 0 → 位置不变
- 返回正数 → 第二个参数排在前面
数字升序和降序的正确写法
升序:用 a - b;降序:用 b - a。这是最简洁、最常用的写法,适用于整数和浮点数。
立即学习“Java免费学习笔记(深入)”;
const nums = [5, 1.2, 10, -3, 0]; nums.sort((a, b) => a - b); // [-3, 0, 1.2, 5, 10] nums.sort((a, b) => b - a); // [10, 5, 1.2, 0, -3]
注意:sort() 是原地修改,会改变原数组。
- 如果不想改原数组,先用
[...arr].sort(...)或arr.slice().sort(...) -
a - b在极端大数下可能精度丢失(如Number.MAX_SAFE_INTEGER + 1),但日常场景几乎不影响
对象数组按字段排序怎么写?
关键在于从对象中取出可比值,再做减法或字符串比较。支持多级排序(例如先按 age 升序,年龄相同时按 name 字典序)。
const users = [
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 },
{ name: 'Charlie', age: 30 }
];
users.sort((a, b) => {
if (a.age !== b.age) return a.age - b.age;
return a.name.localeCompare(b.name);
}); // 先按 age 升序,age 相同则按 name 字典序- 字符串字段必须用
localeCompare(),不能用===或减法 - 字段可能为
undefined或null,建议加空值处理,例如(a?.name || '').localeCompare(b?.name || '') - 大小写敏感?用
.toLowerCase()预处理,或传参给localeCompare
稳定排序和性能要注意什么?
ES2019 起,sort() 必须是稳定排序(相同值的相对顺序不变),但旧版 Chrome/V8 曾不稳定。如果你依赖稳定性(比如分页后合并排序),别假设所有环境都 OK。
- V8(Chrome / Node.js)自 7.0 起已稳定;Firefox 和 Safari 较早支持
-
大数据量(>10 万项)时,
sort()时间复杂度是 O(n log n),但实际性能受比较函数开销影响很大——避免在比较函数里做 DOM 查询、正则匹配等重操作 - 如果只是找 Top-K,用堆或
Array.prototype.reduce()可能比全量排序更快
真正容易被忽略的是:**比较函数里不要有副作用,也不该依赖外部变量状态变化**——sort() 的执行顺序由引擎决定,不可预测。










