Lodash中sortBy、orderBy仅生成新数组?性能及可变版本疑问
关于Lodash中
orderBy和sortBy的不可变设计及可变替代方案 这是个很好的问题,其实背后涉及到Lodash的核心设计理念,我来帮你拆解清楚:
为什么官方选择返回新数组而非修改原数组?
- 遵循函数式编程的纯函数原则:Lodash的很多API都偏向函数式编程风格,而纯函数的关键特征就是不产生副作用——不会修改传入的参数。
orderBy和sortBy作为纯函数,你可以放心调用,不用担心原数组被意外改动,这在多人协作或者复杂状态管理的场景下能避免很多隐蔽的bug。 - 不可变数据的实用性:不可变数据天生更容易追踪变化,比如在React、Vue这类框架中,使用不可变数据能让组件更高效地判断是否需要重新渲染。保留原数组的同时拿到排序后的新数组,也方便你在需要的时候回退到原始数据状态。
- API设计的一致性:Lodash里像
map、filter、concat这类常用数组操作函数,都是返回新数组而不修改原数据。保持这种一致性能让开发者更快上手整个库,不用在不同函数间切换思维模式。
有没有可变版本的排序函数?
Lodash官方确实没有提供orderBy和sortBy的可变版本,但你可以通过两种方式实现类似需求:
手动实现可变版的多维度排序:
基于原生的Array.prototype.sort,你可以自己写一个类似orderBy逻辑的函数,直接修改原数组:// 模拟可变版的orderBy,支持多字段和升降序 function mutableOrderBy(arr, iteratees, orders) { // 处理默认参数,兼容单个字段的情况 iteratees = Array.isArray(iteratees) ? iteratees : [iteratees]; orders = Array.isArray(orders) ? orders : [orders]; arr.sort((a, b) => { for (let i = 0; i < iteratees.length; i++) { // 处理iteratee:支持函数或对象路径字符串 const getValue = typeof iteratees[i] === 'function' ? iteratees[i] : (obj) => obj[iteratees[i]]; const valA = getValue(a); const valB = getValue(b); if (valA !== valB) { // 根据指定的排序方向返回比较结果 const direction = orders[i] === 'desc' ? -1 : 1; return valA > valB ? direction : -direction; } } // 所有字段都相等时返回0 return 0; }); return arr; }调用这个函数后,传入的原数组会被直接排序,同时函数也会返回修改后的数组。
结合Lodash的iteratee和原生sort:
如果你想复用Lodash处理iteratee的能力(比如支持嵌套路径、自定义函数),可以先生成排序用的比较逻辑,再传给原生sort来修改原数组:const _ = require('lodash'); const targetArr = [{name: 'Charlie', age: 28}, {name: 'Alice', age: 25}, {name: 'Bob', age: 30}]; // 生成对应排序规则的iteratee函数 const sortIteratee = _.iteratee(['age', 'asc']); // 用原生sort直接修改原数组 targetArr.sort((a, b) => { const valA = sortIteratee(a); const valB = sortIteratee(b); return valA - valB; // 升序,降序则改为valB - valA });
内容的提问来源于stack exchange,提问作者Noitidart
相关产品推荐
相关产品推荐

