es-toolkit 的 maxBy 函数:按转换值查找数组最大元素的完整指南 📅 发布时间:2026/9/16 10:39:40 👁 浏览次数: es-toolkit 的 maxBy 函数按转换值查找数组最大元素的完整指南【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkitmaxBy是 es-toolkit 数组模块中用于按自定义规则求最大元素的核心工具函数。本文围绕 maxBy 官方文档 展开结合仓库中的 源码实现、单元测试 以及 lodash 兼容版、bigint 版、FP 柯里化版等衍生实现系统讲解其 API 签名、参数语义、返回规则与底层原理。读完本文你将掌握maxBy的完整用法、边界行为空数组、NaN、并列取值、类型重载并能在业务代码中正确选用它来替代手写循环。一、maxBy 是什么maxBy接收一个数组和一个转换函数getValue将数组中的每个元素转换为数值然后返回转换后数值最大的那个原始元素。它解决的是找对象数组中某个属性最大的那条记录这类常见需求而不是简单地对数字本身求最大值那是max的职责。const max maxBy(items, getValue);maxBy通过 src/array/index.ts 从es-toolkit/array入口导出可通过以下方式引入import { maxBy } from es-toolkit/array; // 或从全量入口引入 import { maxBy } from es-toolkit;二、基本用法与典型场景官方文档给出的核心使用方式是当你需要把数组元素经转换函数映射为数值、并找出转换后值最大的原始元素时使用maxBy。空数组时返回undefined。场景一对象数组中按属性求最大import { maxBy } from es-toolkit/array; // 找出年龄最大的人 const people [ { name: john, age: 30 }, { name: jane, age: 28 }, { name: joe, age: 26 }, ]; maxBy(people, person person.age); // Returns: { name: john, age: 30 }场景二按计算值求最大// 找出绝对值最大的数字 const numbers [-10, -5, 0, 5, 15]; maxBy(numbers, x Math.abs(x)); // Returns: 15注意转换函数返回的是比较基准值如Math.abs(x)但maxBy返回的是原始元素如15这是它与Math.max的根本区别。场景三空数组返回 undefinedmaxBy([], x x.value); // undefined三、参数与返回值参数参数类型说明itemsT[]待查找最大元素的数组getValue(element: T, index: number, array: readonly T[]) number将每个元素转换为数值的比较函数依次接收元素、元素下标、原数组三个参数getValue的第三个参数array是只读数组引用可用于基于数组整体信息如长度参与计算index参数则支持值 位置复合排序逻辑例如(item, index) item.value index。返回值T \| undefined转换函数返回值中最大者对应的原始元素数组为空时返回undefined。四、源码级原理剖析maxBy的实现位于 src/array/maxBy.ts核心逻辑非常精简export function maxByT(items: readonly T[], getValue: ...): T | undefined { if (items.length 0) { return undefined; } let maxElement items[0]; let max -Infinity; for (let i 0; i items.length; i) { const element items[i]; const value getValue(element, i, items); if (Number.isNaN(value)) { return element; } if (value max) { max value; maxElement element; } } return maxElement; }从实现中可以提取出以下可验证的行为规则1. 空数组短路返回 undefined函数第一行就对items.length 0做了短路判断因此空数组不会调用getValue直接返回undefined对应 maxBy.spec.ts 中的空数组用例。2. 初始值使用 -Infinitymax初始化为-Infinity保证即使所有转换值都是负数如[-5, -3, -1]第一个元素也能正常参与比较并胜出。maxElement初始化为items[0]因此单元素数组会直接返回唯一元素见测试用例 maxBy.spec.ts。3. 严格大于比较并列时取第一个比较使用value max严格大于而非意味着当多个元素转换值并列最大时返回最早出现的那个。测试 maxBy.spec.ts 明确验证了这一点Mark(25)、Nunu(30)、Overmars(30)中返回Nunu。4. NaN 立即传播与 Math.max 行为一致实现中一旦getValue返回Number.isNaN(value)为真就立即返回产生该 NaN 的元素而不是忽略它继续比较。这是刻意设计Math.max遇到 NaN 会返回 NaNmaxBy保持了这一语义。测试 maxBy.spec.ts 验证了 NaN 无论位于数组开头、中间还是末尾都会传播expect(maxBy([Number.NaN, 1, 3, 2], x x)).toBeNaN(); expect(maxBy([1, Number.NaN, 3, 2], x x)).toBeNaN(); expect(maxBy([1, 3, 2, Number.NaN], x x)).toBeNaN();5. 单次线性遍历无额外开销整个查找只做一次for循环时间复杂度为 O(n)没有排序、没有中间数组拷贝这也是 es-toolkit 强调小而快的体现。仓库在 benchmarks/performance/maxBy.bench.ts 中提供了与lodash/maxBy的对比基准分别针对小数组和 10000 元素大数组你可以在本地运行 benchmark 验证其性能表现。五、类型签名中的重载设计maxBy的类型定义采用了函数重载用于在类型层面区分空数组与非空数组// 重载 1非空元组readonly [T, ...T[]]保证至少一个元素返回类型为 T export function maxByT( items: readonly [T, ...T[]], getValue: (element: T, index: number, array: readonly T[]) number ): T; // 重载 2普通数组可能为空返回类型为 T | undefined export function maxByT( items: readonly T[], getValue: (element: T, index: number, array: readonly T[]) number ): T | undefined;这一设计的价值在于当你传入一个保证非空的元组类型如[{ a: 1 }, { a: 2 }] as const或带有非空约束的数组时TypeScript 会自动匹配第一个重载返回值类型收窄为T调用方无需再做undefined判空而传入普通数组时返回T | undefined强制调用方处理空数组情况从类型系统层面杜绝运行时错误。六、getValue 回调的完整参数getValue是一个标准的(element, index, array) number回调三个参数都可在实际业务中发挥作用// 使用 index 参数位置参与排序 const items [{ value: 10 }, { value: 20 }, { value: 15 }]; maxBy(items, (item, index) item.value index); // Returns: { value: 20 } // 使用 array 参数基于数组整体信息计算 maxBy(items, (item, _index, array) item.value * array.length); // Returns: { value: 20 }以上两个示例来自 英文版官方文档并在 maxBy.spec.ts 中有对应的测试用例覆盖。七、相关实现与变体围绕maxBy仓库中还提供了多个面向不同场景的变体实现选择时需注意行为差异1. bigint 版src/bigint/maxBy.ts针对大整数场景bigint 模块的 maxBy 要求getValue返回bigint比较基于 bigint 语义。与主版本最关键的区别是空数组会抛出RangeErrorCannot find the maximum of an empty array.而不是返回undefined——因为 bigint 场景通常要求数据非空用异常代替静默失败更安全import { maxBy } from es-toolkit/bigint; const accounts [{ balance: 10n }, { balance: 30n }, { balance: 20n }]; maxBy(accounts, account account.balance); // Returns: { balance: 30n }2. lodash 兼容版src/compat/math/maxBy.ts如果你是从 lodash 迁移而来可以使用es-toolkit/compat入口的 兼容版 maxBy。它在主版本的基础上扩展了iteratee的四种形式函数x x.a从元素中提取数值与主版本一致字符串键a等价于x x.a[key, value]键值对[a, 1]先按匹配筛选再求最大对象{ a: 1 }匹配包含指定属性的元素再求最大。同时兼容版还做了额外健壮性处理接受null/undefined输入返回undefined、跳过转换值为null/NaN/symbol的元素、并支持ArrayLike类数组对象。import { maxBy } from es-toolkit/compat; maxBy([{ a: 1 }, { a: 2 }], a); // Returns: { a: 2 } maxBy([{ a: 1 }, { a: 2 }], [a, 1]); // Returns: { a: 1 } maxBy([{ a: 1 }, { a: 2 }], { a: 1 }); // Returns: { a: 1 }3. FP 柯里化版src/fp/array/maxBy.ts函数式编程入口 src/fp/array/maxBy.ts 提供柯里化形式先传入getValue返回一个接收数组的函数天然适配pipe/flow数据流import { maxBy, pipe } from es-toolkit/fp; pipe([{ score: 10 }, { score: 20 }] as const, maxBy(item item.score)); // Returns: { score: 20 } pipe([] as Array{ score: number }, maxBy(item item.score)); // Returns: undefinedFP 版的空数组行为与主版本保持一致返回undefinedNaN 传播语义也完全相同。八、边界行为速查综合官方文档、源码与测试maxBy的边界行为可归纳为下表输入场景行为空数组[]返回undefined单元素数组返回唯一元素多个元素转换值并列最大返回最先出现的元素任一元素转换值为 NaN返回产生该 NaN 的元素与Math.max一致所有转换值均为负数正常返回最大负数对应的元素初始值-Infinity保证正确性bigint 版空数组抛出RangeErrorcompat 版null/undefined输入返回undefined九、与 max / minBy 的关系maxBy与 es-toolkit 数组模块中的max、minBy是同一家族max对数值数组本身求最大值不涉及转换函数maxBy按转换函数求最大原始元素minBy按转换函数求最小原始元素src/array/minBy.ts实现逻辑与maxBy对称仅比较方向相反。选型建议数据已经是纯数字数组时用max数据是对象数组、需要按属性或计算值比较时用maxBy/minBy。maxBy的英文版文档位于 docs/reference/array/maxBy.md日文版即 docs/ja/reference/array/maxBy.md可作为 API 速查参考。十、小结maxBy是 es-toolkit 中按规则求最大元素的标准答案一次线性遍历、无中间分配正确处理空数组与 NaN 传播并通过类型重载在编译期约束空数组风险。无论是对象数组按属性求最值、按计算值求最值还是通过 FP 变体接入管道式数据处理它都能以极简 API 替代手写循环同时在 基准测试 中保持与 lodash 可比、且包体更小的优势。需要大整数或 lodash 全兼容语义时可分别切换到es-toolkit/bigint与es-toolkit/compat的对应实现。【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考