javascript中可通过高阶函数multisortby构造动态多字段排序函数,接收规则数组并返回适配sort()的比较函数,支持嵌套属性、自定义比较器及空值策略。

JavaScript 中可以通过高阶函数构造一个可复用、支持多字段(含升序/降序)的动态排序函数,核心是返回一个适配 Array.prototype.sort() 的比较函数。
一、理解高阶函数在排序中的作用
高阶函数指接受函数为参数或返回函数的函数。这里我们定义一个函数 multiSortBy,它接收排序规则(如 [{key: 'name', dir: 'asc'}, {key: 'age', dir: 'desc'}]),返回一个可用于 sort() 的比较函数。这样就能把“排序逻辑”和“数据”解耦,实现动态配置。
二、基础实现:支持字符串/数字字段的多级排序
以下是一个轻量、健壮的实现,自动处理 null、undefined、NaN 和类型不一致的情况:
(复制即可用)
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const multiSortBy = (rules) => {
return (a, b) => {
for (let rule of rules) {
const { key, dir = 'asc' } = rule;
let va = a?.[key];
let vb = b?.[key];
// 统一处理 null/undefined:排在最后(升序时),或最前(降序时)
if (va == null && vb == null) continue;
if (va == null) return dir === 'asc' ? 1 : -1;
if (vb == null) return dir === 'asc' ? -1 : 1;
// 字符串忽略大小写比较;数字直接比;其他转字符串兜底
if (typeof va === 'string' && typeof vb === 'string') {
va = va.toLowerCase();
vb = vb.toLowerCase();
}
let diff = va > vb ? 1 : va
<p>使用示例:</p>
<pre class="brush:php;toolbar:false;">const users = [
{ name: 'Alice', age: 30, score: 85 },
{ name: 'bob', age: 25, score: 92 },
{ name: 'Charlie', age: 30, score: 78 }
];
users.sort(multiSortBy([
{ key: 'age', dir: 'asc' }, // 先按年龄升序
{ key: 'name', dir: 'asc' } // 年龄相同时按姓名升序(忽略大小写)
]));
// → [{ name: 'bob', age: 25, ... }, { name: 'Alice', age: 30, ... }, { name: 'Charlie', age: 30, ... }]
三、增强能力:支持嵌套字段与自定义比较器
若需按 address.city 或 profile.rating 排序,可扩展 get 工具函数;若需特殊逻辑(如按中文拼音、日期对象、空值优先),可通过 compare 自定义函数注入:
const multiSortBy = (rules) => {
const get = (obj, path) => path.split('.').reduce((o, k) => o?.[k], obj);
return (a, b) => {
for (let rule of rules) {
const { key, dir = 'asc', compare } = rule;
let va = get(a, key);
let vb = get(b, key);
if (compare) {
const result = compare(va, vb);
if (result !== 0) return dir === 'desc' ? -result : result;
} else {
// 原有默认逻辑(略,同上)
if (va == null && vb == null) continue;
if (va == null) return dir === 'asc' ? 1 : -1;
if (vb == null) return dir === 'asc' ? -1 : 1;
if (typeof va === 'string' && typeof vb === 'string') {
va = va.toLowerCase();
vb = vb.toLowerCase();
}
const diff = va > vb ? 1 : va
<p>嵌套字段示例:</p>
<pre class="brush:php;toolbar:false;">const data = [
{ user: { name: 'Tom', dept: 'eng' } },
{ user: { name: 'Jerry', dept: 'design' } }
];
data.sort(multiSortBy([{ key: 'user.name', dir: 'asc' }]));
自定义比较器示例(按中文首字拼音排序):
data.sort(multiSortBy([{
key: 'name',
compare: (a, b) => a.localeCompare(b, 'zh-Hans-CN')
}]));
四、实用建议与注意事项
- 保持纯函数:不要在比较函数中修改原数组或外部状态,确保可预测性
- 避免重复计算:如果字段取值开销大(如调用方法),可在排序前预处理成临时字段
-
注意稳定性:ES2019+ 的
Array.prototype.sort()是稳定排序,相同键值的相对位置不变,这点对多字段排序很关键 -
空值策略可配置:当前实现将
null/undefined排在末尾(升序),如需前置,改对应分支的返回值即可
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










