Array.prototype.sort()自ECMAScript 2019起为稳定排序,多级排序须从最低优先级字段开始逐次向前叠加高优先级排序,以利用稳定性保持相同高优先级元素的原有相对顺序。

Array.prototype.sort() 在现代浏览器中已是稳定排序(ECMAScript 2019 起正式要求),这意味着相等元素的相对顺序不会改变。利用这一特性,可以安全地进行多级排序——通过多次调用 sort(),从**最低优先级字段开始,逐级向前叠加高优先级排序**,从而保证最终结果逻辑一致、可预测。
为什么“倒序执行”是关键
稳定性让后一次排序不会破坏前一次排序中已确立的次序关系。若先按高优先级排,再按低优先级排,低优先级的重排会打乱高优先级下原本有序的组内顺序;而反过来:先按低优先级排好,再按高优先级重排,相同高优先级的元素会保持它们在低优先级排序中的原有先后关系——这正是多级排序所需的分组内保序行为。
实现多级排序的正确步骤
- 从最不重要的排序字段开始(例如:先按
city升序) - 接着按次重要字段排序(例如:再按
age升序) - 最后按最重要字段排序(例如:最后按
name升序) - 每次比较函数只关注当前一级字段,返回 -1 / 0 / 1
实际代码示例
对用户数组按「部门(dept)升序 → 入职年份(year)降序 → 姓名(name)升序」排序:
const users = [
{ name: '张三', dept: '技术', year: 2022 },
{ name: '李四', dept: '市场', year: 2021 },
{ name: '王五', dept: '技术', year: 2021 }
];
<p>// ✅ 正确:从低优先级到高优先级依次 sort
users.sort((a, b) => a.name.localeCompare(b.name)); // 第三优先级
users.sort((a, b) => b.year - a.year); // 第二优先级(降序)
users.sort((a, b) => a.dept.localeCompare(b.dept)); // 第一优先级</p><p>// 结果:同部门内按入职年份降序,年份相同时按姓名升序</p>注意事项与常见误区
不要在一个 compare 函数里写多条件判断来“一步到位”——虽然可行,但逻辑易错、难以复用、且掩盖了稳定性带来的组合优势。更推荐拆解为多次稳定排序,清晰、可维护、便于调试。
注意 null/undefined 和类型不一致字段:比较前建议统一转换(如转字符串或提供默认值),否则 undefined - 1 会得 NaN,导致排序异常。
性能并非问题:现代 V8 对多次 sort 有优化,且稳定性保障下,三次排序的开销远低于手动实现复杂多级 compare 的心智负担。

















