柯里化比较器是将多参数排序函数拆分为单参数函数,先传字段名或取值函数,返回可直接用于sort()的比较函数;支持属性名、嵌套路径、升降序及自定义取值,具备复用性、灵活性和类型安全处理能力。

在 JavaScript 数组排序中,用柯里化构造比较器,能灵活固定排序字段(比如按 name 或 age),避免重复写逻辑,也方便复用和组合。
什么是柯里化比较器
柯里化就是把一个多参数函数拆成一系列单参数函数。对排序来说,就是先传入字段名(或取值函数),返回一个可直接用于 Array.prototype.sort() 的比较函数。
例如:sortBy('age') 返回一个函数,它接收两个对象,比较它们的 age 值。
基础实现:按属性名排序
支持字符串字段名,自动提取属性值,并处理 undefined / null / 类型不一致的情况:
const sortBy = (key) => (a, b) => {
const valA = a?.[key];
const valB = b?.[key];
<p>// 处理 null/undefined:排在后面(升序)
if (valA == null && valB == null) return 0;
if (valA == null) return 1;
if (valB == null) return -1;</p><p>// 字符串统一转小写比较,数字直接减
if (typeof valA === 'string' && typeof valB === 'string') {
return valA.localeCompare(valB);
}
return valA valB ? 1 : 0;
};</p><p>// 使用
const users = [{ name: 'Bob', age: 30 }, { name: 'Alice', age: 25 }];
users.sort(sortBy('age')); // 按 age 升序
users.sort(sortBy('name')); // 按 name 升序(忽略大小写)
</p>增强版:支持路径、方向、自定义取值
用柯里化叠加更多配置,比如支持嵌套字段('profile.city')、降序、或传入取值函数:
- 用
_.get风格路径访问嵌套属性(或自己简单实现) - 第二个参数控制升序/降序(
1升序,-1降序) - 允许传入 getter 函数替代字段名,更灵活
const sortBy = (keyOrGetter, direction = 1) => {
const getVal = typeof keyOrGetter === 'function'
? keyOrGetter
: (obj) => obj?.[keyOrGetter] ?? obj?.[keyOrGetter.split('.')[0]]?.[keyOrGetter.split('.')[1]];
<p>return (a, b) => {
const valA = getVal(a);
const valB = getVal(b);</p><pre class="brush:php;toolbar:false;">if (valA == null && valB == null) return 0;
if (valA == null) return direction;
if (valB == null) return -direction;
if (typeof valA === 'string' && typeof valB === 'string') {
return direction * valA.localeCompare(valB);
}
return direction * (valA valB ? 1 : 0);
}; };
// 示例 data.sort(sortBy('price', -1)); // 价格降序 data.sort(sortBy(obj => obj.tags?.length)); // 按标签数量升序
实用技巧:组合与缓存
柯里化后函数是纯的,可安全复用和预生成:
- 提前定义常用排序器:
const byName = sortBy('name');,后续直接arr.sort(byName) - 组合多个字段:用
thenBy实现多级排序(如先按 status,再按 createdAt) - 配合
Object.freeze或模块导出,避免意外修改
不复杂但容易忽略:确保比较器始终返回数字(-1 / 0 / 1),否则 sort 行为可能因引擎而异。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











