Lodash 数组方法怎么用,什么时候比原生数组更合适?
Lodash 的数组方法不是为了替代所有原生数组 API。map、filter、find 这些原生方法已经很好用,真正值得保留 Lodash 的地方,是分组、去重、差集、排序、分块这类边界稍微复杂的处理。判断要不要用 Lodash,可以先问一句:这段逻辑用原生写法会不会绕、会不会容易漏边界?如果答案是会,再引入工具方法就比较划算。
分块和清洗:chunk、compact、flatten
chunk 常用于分页展示、批量请求、分批渲染。它的价值在于让“每 N 个一组”的意图直接出现在代码里。
jsimport chunk from 'lodash/chunk'; import compact from 'lodash/compact'; import flatten from 'lodash/flatten'; const pages = chunk(products, 20); const ids = compact([0, 12, null, 31, undefined, '']); const flatTags = flatten([['js', 'lodash'], ['array']]);
不过 compact 会移除所有假值,包括 0、false、空字符串。这个边界很重要,订单金额为 0、开关值为 false 都可能是合法数据。清洗表单时如果只是想去掉 null 和 undefined,不要直接用 compact。
去重和集合运算:uniq、uniqBy、difference
数组去重是 Lodash 很常见的使用场景。基础值用 uniq,对象数组按字段去重用 uniqBy,两个集合之间找差异用 difference 或 differenceBy。
jsimport uniq from 'lodash/uniq'; import uniqBy from 'lodash/uniqBy'; import differenceBy from 'lodash/differenceBy'; uniq([1, 1, 2]); // [1, 2] const users = uniqBy(list, 'id'); const removed = differenceBy(oldUsers, newUsers, 'id');
如果数据量很大,原生 Set 在简单去重上通常更轻,也更快:
jsconst uniqueIds = [...new Set(ids)];
但对象数组去重、按字段比较、按规则求差集时,Lodash 的表达力更好。取舍点就是简单值优先原生,复杂对象再用 Lodash。
排序、分组和聚合:sortBy、orderBy、groupBy
业务列表经常要按状态分组、按时间排序、按多个字段排序。sortBy 适合升序排序,orderBy 可以分别指定字段和方向,groupBy 能把分类逻辑写得很短。
jsimport groupBy from 'lodash/groupBy'; import orderBy from 'lodash/orderBy'; const grouped = groupBy(tickets, 'status'); const sorted = orderBy( tickets, ['priority', 'createdAt'], ['desc', 'asc'] );
这里的坑是 groupBy 的 key 会被转成字符串,true、false、数字状态码都会变成对象属性名。排序时也要注意时间字段格式,字符串日期如果不是标准 ISO 格式,排序结果可能和你想的不一样。
追问
Lodash 的 map、filter 还值得用吗?
大多数情况下不值得,原生 Array.prototype.map 和 filter 已经足够清楚,也不会增加额外依赖。Lodash 的优势是能统一处理类数组、对象集合等老场景,但现代前端里这种需求少了很多。取舍上,团队新代码可以优先原生数组方法,只在需要 Lodash 特性时引入。踩坑点是混用过多风格,代码审查时很难形成稳定习惯。
compact 清理数组为什么可能出错?
因为它清理的是所有 falsy 值,不是只清理空值。0、false、'' 在很多业务里都有明确含义,比如库存为 0、开关关闭、备注为空字符串。边界在于你要先定义“脏数据”到底是什么,而不是把所有看起来空的值都删掉。如果只想删除 null 和 undefined,用 filter(v => v != null) 更准确。
uniqBy 去重时保留哪一条数据?
uniqBy 会保留第一次出现的那条记录,后面相同 key 的记录会被丢掉。这个行为在去重搜索结果时很方便,但在合并最新用户信息时可能不对,因为你也许想保留最后一次更新的数据。取舍点是先明确“重复时谁优先”,再决定用 uniqBy、反转数组,还是用 Map 手动覆盖。很多线上问题不是去重失败,而是保留了旧数据。
groupBy 适合直接拿来渲染列表吗?
可以,但要注意它返回的是对象,不是有顺序保证的分组数组。状态分组如果要按“待处理、处理中、已完成”的顺序展示,最好再配一份顺序配置,而不是依赖对象 key 的遍历结果。边界还包括空分组,groupBy 不会自动生成没有数据的分类。做后台管理页时,这些空状态通常也要展示,否则用户会以为状态不存在。
大数组处理用 Lodash 会不会影响性能?
会有可能,尤其是链式调用里多次遍历数组时。几千条数据一般问题不大,但几十万条数据就应该关注遍历次数、内存分配和是否能提前终止。Lodash 让代码更短,不代表算法成本消失了。性能敏感场景可以用原生循环、生成器、服务端分页或 Web Worker,别把所有压力都压在一个前端工具函数上。
数组方法最好放在数据整理边界,而不是散落在视图模板里。比如接口返回后先完成去重、排序、分组,再把结果交给组件渲染,组件代码会轻很多。这样做的代价是中间变量会多一些,但换来的是更好测试和更少重复计算。尤其在列表页,数据整理逻辑越早收口,后面越不容易出现同一份数据被多处用不同规则处理的问题。
小结
Lodash 数组方法适合处理“原生能做但写起来容易散”的问题,比如对象去重、多字段排序、分组和批处理。简单映射、过滤、基础去重优先用原生 API,复杂集合逻辑再引入 Lodash。这样代码既不会显得笨重,也能在真正有边界的地方少踩坑。