sort默认按字符串Unicode排序导致数字错乱;数字排序需传(a,b)=>a-b;对象按属性排序要处理undefined,字符串用localeCompare,多级排序用短路逻辑。

sort 方法默认按字符串排序,数字会出错
JavaScript 的 sort() 方法不传参时,会把数组元素先转成字符串,再按 Unicode 码点排序。这意味着 [10, 2, 33, 1] 会变成 [1, 10, 2, 33],因为 "10" 为 true。
这不是 bug,是设计如此 —— 它只保证“稳定比较”,不保证数值逻辑正确。
- 对纯字符串数组(如
["banana", "apple", "cherry"]),默认行为可用 - 只要含数字、或需按大小/日期/对象字段排序,就必须传比较函数
- 空值(
null、undefined)在转换中会变成"null"或"undefined",进一步扰乱顺序
写比较函数:必须返回负数、0 或正数
sort() 的比较函数接收两个参数 a 和 b,它只关心返回值的符号:
- 返回
→a排在b前面 - 返回
0→a和b位置不变(稳定排序) - 返回
> 0→a排在b后面
升序数字排序最简写法:
立即学习“Java免费学习笔记(深入)”;
numbers.sort((a, b) => a - b);
降序则反过来:
numbers.sort((a, b) => b - a);
注意:不能写 return a > b,那只会返回布尔值(true/false),被转成 1/0,导致排序错误或不稳定。
处理对象数组:按属性排序要小心 undefined
比如按 users 数组里的 age 升序排:
users.sort((a, b) => (a.age || 0) - (b.age || 0));
但更健壮的做法是显式处理缺失值,避免 undefined - 5 得到 NaN:
- 用
??提供默认值:(a.age ?? 0) - (b.age ?? 0) - 或提前过滤:
users.filter(u => u.age != null).sort(...) - 若想把缺失
age的项排最后,可写:return (a.age == null) - (b.age == null) || a.age - b.age;
字符串属性(如 name)建议用 localeCompare,支持大小写与本地化:
users.sort((a, b) => a.name.localeCompare(b.name));
多级排序:链式判断别用嵌套 if
要先按 status('active' > 'pending' > 'archived'),再按 createdAt 时间倒序,别这么写:
if (a.status !== b.status) { return ... } else { return ... }而是用「短路」逻辑,一行搞定:
items.sort((a, b) => {
const statusOrder = { active: 0, pending: 1, archived: 2 };
const byStatus = (statusOrder[a.status] || 99) - (statusOrder[b.status] || 99);
return byStatus || new Date(b.createdAt) - new Date(a.createdAt);
});关键点:
- 第一项比较结果非零就直接返回,否则用
||继续下一项 - 时间比较记得转
Date对象,否则字符串时间(如"2023-01-01")仍走字典序 - 原地修改数组,记得必要时用
[...arr].sort(...)避免副作用
sort 的比较函数看似简单,但边界情况(null、NaN、时区、Unicode)最容易漏掉。每次写之前,先问一句:这个 a 和 b 可能是什么值?










