作为一名前端开发,大部分应该都接触过 Lodash,但现如今,Lodash 显得既老又蹩脚,Radash 又新又酷。 你还需要知道什么?
Lodash存在的问题
一直以来,Lodash 通过降低array、number、objects、string 等等的使用难度从而让JavaScript 变得更简单。但前端发展至今,纯函数、函数式编程的理念已经在社区深深扎根!而Lodash在这些方面略显落后。
作为一个创建于十多年前的工具库,Lodash的设计和开发是为了解决十多年前 Javascript 开发人员的问题,但很多问题对于现在的我们再也不是问题了。更不用说随着 Typescript 的兴起, 像 Lodash 这样基础的软件包理应提供有用的类型判断。
过时的功能函数
接下来让我介绍一下 Lodash 的一些功能,阐述为什么它们已经过时并不再适合你的项目。
_.get 函数允许你将字符串或数组值传递给第二个参数,即路径参数。当初这么设计是为了动态匹配更多的参数情况,但现在却可能导致一些错误产生。 比如在 Typescript 中,代码 _.get({ name: 'ray' }, 'age') 是不会产生错误的,因为 Lodash 不会验证对象中是否存在给定的字符串路径。
这个功能函数存在以下三点问题:
- 该函数接受不同类型作为第二个参数,同一个参数类型多样导致了许多不确定的问题。
- 当传递对象、数组或字符串时,这些类型不起作用。 由于 Lodash 的类型能力较差,Typescript 无法检查传递的值是否存在于所提供数组的类型上。
- 由于空合并和可选链的存在,过滤器函数有点过时了。 当空值检查需要多行代码才能安全地执行时,这很有帮助,但现在可以使用
?和??实现上图中的任何功能,并且代码更简短。
空值合并
const foo = null ?? 'default value';
console.log(foo); // 输出: 'default value'
可选链
const obj = { foo: { bar: 'value' } };
const value = obj.foo?.bar;
类似的问题还可以在 _.find 和 _.some 函数上看到。
另外,还有像 _.map 和 _.size 这样的函数,它们不仅具有上述的问题,并且能够接受各种值作为第一个和第二个参数,让使用变得更加复杂。
源码可读性差
如果说上面的那些问题还在我们接受范围内的话,那么 Lodash 源码的学习成本真的很高,因为有时候我们是需要能快速查看源码类协助排查问题的。
这是 Lodash 的一个源码链接,大家可以看一看有多难读了。
如果仅仅是为了了解一个简单的函数实现,就得读成千上万行代码,只能说这个代码写的是真绕!
例如,我想要了解 isString 是如何实现的,我们来看看它有多繁琐:
- 首先找到 isString 的定义:
function isString(value) {
return typeof value == 'string' ||
(!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
}
- 接着找到其中使用到的 isObjectLike:
function isObjectLike(value) {
return value != null && typeof value == 'object';
}
- 然后找到其中使用到的 baseGetTag:
function baseGetTag(value) {
if (value == null) {
return value === undefined ? undefinedTag : nullTag;
}
return (symToStringTag && symToStringTag in Object(value))
? getRawTag(value)
: objectToString(value);
}
可以看到,这里又又又引出了两个新函数 getRawTag、objectToString。这就像无限套娃一样,深不见底!
Radash初识
正因为 Lodash 存在这样那样的问题,社区广大的诉求得不到解决,在这种背景下 Radash 崛起了。
Radash 号称是下一个你不能没有的库,让我们看看它有哪些特点:
- • 它是用 Typescript 编写的,非常强大且有用,类型是预先打包的。
- • 它省略了 Lodash 多年来已经过时的功能
- • 它提供了您以前从未见过但一直想要的新功能(见下文)
- • 源代码的维护以新手的可理解性为首要任务。 在大多数情况下,如果您想使用 Radash 函数但不想安装它,您应该能够直接从 GitHub 复制它。
实用新功能
接下来为大家介绍它提供的众多实用功能。
tryit 函数
功能是将函数转换为错误优先函数
import { tryit } from 'radash'
const [err, user] = await tryit(api.users.find)(userId)
写过node接口层的同学应该很熟吧,tryit 函数让您可以包装一个函数,将其转换为错误优先函数。 适用于异步和同步功能。
这样就不再需要像使用 try catch一样,在 try 外部创建可变的 let 变量,将其设置在内部,然后再检查它。
parallel 函数
功能是并行运行多个异步函数。
它已成为 Promise.all 的直接替代品,不仅可以控制一次发出的请求数量,而且错误处理也更好。
import { parallel } from 'radash'
const userIds = [1, 2, 3, 4, 5, 6, 7, 8, 9]
// Will run the find user async function 3 at a time
// starting another request when one of the 3 is freed
const users = await parallel(3, userIds, async (userId) => {
return await api.users.find(userId)
})
retry 函数
功能是运行异步函数,如果失败则重试。
_.retry 函数允许您运行异步函数并在失败时自动重试。 给定要运行的异步函数、可选的最大重试次数 (r) 以及重试之间的可选延迟毫秒数 (d),将调用给定的异步函数,重试 r 次,并在重试之间等待 d 毫秒。
import { retry } from 'radash'
await retry({}, api.users.list)
await retry({ times: 10 }, api.users.list)
await retry({ times: 2, delay: 1000 }, api.users.list)
// exponential backoff
await retry({ backoff: i => 10**i }, api.users.list)
结合尝试、并行和重试,它可以替换大多数后端服务容错库的工具。
counting 函数
功能是用于统计数组中满足特定条件的元素个数。
如统计年龄大于30的人数:
import { counting } from 'radash';
const people = [
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 },
{ name: 'Charlie', age: 35 }
];
const olderThan30Count = counting(person => person.age > 30, people);
console.log(olderThan30Count); // 输出: 1
range 函数
功能是创建一个包含指定范围内数字的数组。
1 .如:生成一段连续的数字范围
import { range } from 'radash';
const numbers = range(1, 5); // 生成包含 1 到 5 的数字数组
console.log(numbers); // 输出: [1, 2, 3, 4, 5]
- 1. 如:指定步长生成数字范围
import { range } from 'radash';
const numbers = range(5, 0, -1); // 生成包含从 5 到 0 的递减数字的数组
console.log(numbers); // 输出: [5, 4, 3, 2, 1, 0]
list 函数
功能是创建一个包含指定元素的数组。
- 1. 如:创建包含重复元素的数组
import { list } from 'radash';
const repeatedNumbers = list(3, 0); // 创建包含3个重复的数字0的数组
console.log(repeatedNumbers); // 输出: [0, 0, 0]
- 1. 如:创建包含自定义元素的数组
import { list } from 'radash';
const customList = list(4, (index) => index + 1); // 创建一个包含1到4的数字的数组
console.log(customList); // 输出: [1, 2, 3, 4]
还有很多更神奇的功能,比如这些常用的功能:
- objectify and listify
- throttle and debounce
- pick and omit
- compose and chain
- memo and proxied
当然,Lodash 作为发展了这么多年的工具库,无论生态和存量应用都比 Radash 大得多,但对于新项目来说,它会是更值得推荐的一个。你会愿意使用它么?
我是斌少,十年经验大厂全栈开发,多年一线leader,分享编程经验、技术干货,帮你少走弯路、快速成长。