项目里总有些通用的数据处理逻辑,自己写容易出bug,用Lodash又觉得只用了冰山一角。
今天整理一批真正高频、真正好用的Lodash方法,都是我在项目里反复用到的。
对象处理
get:安全取值,不用再写一堆三元
// 原生写法
const name = res && res.data && res.data.user && res.data.user.name;
// Lodash
const name = _.get(res, 'data.user.name', '默认值');
// 数组下标也支持
const first = _.get(list, '[0].name');
这是我用得最多的一个方法,深层次的接口返回,用它省心。
pick / omit:筛选字段
const user = { id: 1, name: '张三', password: 'xxx', token: 'abc' };
// 只保留指定字段
_.pick(user, ['id', 'name']);
// { id: 1, name: '张三' }
// 排除指定字段(防止敏感信息返回前端)
_.omit(user, ['password', 'token']);
// { id: 1, name: '张三' }
merge / defaults:合并配置
const defaultConfig = {
pageSize: 10,
orderBy: 'createTime',
orderDir: 'desc',
filters: { status: 'ALL' }
};
const userConfig = {
pageSize: 20,
filters: { status: 'PAID' }
};
_.merge({}, defaultConfig, userConfig);
// { pageSize: 20, orderBy: 'createTime', orderDir: 'desc', filters: { status: 'PAID' } }
merge会深合并,assign只会浅覆盖。配置合并的场景一定要用merge。
数组处理
uniqBy:按字段去重
const list = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
{ id: 1, name: 'A副本' }
];
_.uniqBy(list, 'id');
// [{ id: 1, name: 'A' }, { id: 2, name: 'B' }]
比new Set()好用多了,Set只能对基本类型去重。
groupBy:分组
const orders = [
{ id: 1, status: 'PAID' },
{ id: 2, status: 'UNPAID' },
{ id: 3, status: 'PAID' }
];
_.groupBy(orders, 'status');
// {
// PAID: [{ id: 1 }, { id: 3 }],
// UNPAID: [{ id: 2 }]
// }
sortBy:多字段排序
_.sortBy(list, ['status', 'createTime']);
// 先按status排,相同再按createTime排
chunk:数组分块
_.chunk([1, 2, 3, 4, 5, 6, 7], 3);
// [[1,2,3], [4,5,6], [7]]
批量请求的时候特别有用:
const batches = _.chunk(ids, 100);
for (const batch of batches) {
await api.batchQuery(batch);
}
difference / intersection:集合运算
const oldIds = [1, 2, 3, 4];
const newIds = [3, 4, 5, 6];
_.difference(newIds, oldIds); // [5, 6] 新增的
_.difference(oldIds, newIds); // [1, 2] 删除的
_.intersection(oldIds, newIds); // [3, 4] 共有的
做数据同步的时候,这三个方法能省一堆代码。
函数工具
debounce / throttle
const search = _.debounce(function(keyword) {
api.search(keyword);
}, 300);
const onScroll = _.throttle(function() {
updatePosition();
}, 200);
比自己手写省事,而且cancel/flush这些方法都有。
memoize:缓存计算结果
const expensiveCalc = _.memoize(function(n) {
console.log('计算中...');
return n * n;
});
expensiveCalc(5); // 计算中... 25
expensiveCalc(5); // 25(直接返回缓存)
注意:默认只缓存第一个参数,多参数要自己写resolver。
const calc = _.memoize(
(a, b) => a + b,
(a, b) => `${a}-${b}` // 自定义缓存key
);
cloneDeep:深拷贝
const copy = _.cloneDeep(original);
比JSON.parse(JSON.stringify())靠谱,能处理Date、RegExp、循环引用。
判断工具
_.isEmpty([]); // true
_.isEmpty({}); // true
_.isEmpty(''); // true
_.isEmpty(null); // true
_.isEmpty(0); // true(这个要注意)
_.isEqual({ a: 1 }, { a: 1 }); // true(深比较)
_.isNil(null); // true(null或undefined)
_.isPlainObject({}); // true(纯对象)
_.isEmpty(0)返回true这个坑我踩过,数字0会被当成空。判断数组空还是用arr.length === 0更稳妥。
按需引入
Lodash全量引入有70KB+,按需引入能砍到几KB:
// 不好
import _ from 'lodash';
// 好
import get from 'lodash/get';
import debounce from 'lodash/debounce';
// 更好(配合babel-plugin-lodash自动处理)
import { get, debounce } from 'lodash';
现在很多方法原生JS也能实现了(Object.groupBy、Array.prototype.at),但Lodash的兼容性和便利性依然有优势。选几个高频的用起来,开发效率提升很明显。