你还在使用Lodash吗?那你就out了

979 阅读6分钟

作为一名前端开发,大部分应该都接触过 Lodash,但现如今,Lodash 显得既老又蹩脚,Radash 又新又酷。 你还需要知道什么?

Lodash存在的问题

一直以来,Lodash 通过降低array、number、objects、string 等等的使用难度从而让JavaScript 变得更简单。但前端发展至今,纯函数、函数式编程的理念已经在社区深深扎根!而Lodash在这些方面略显落后。
作为一个创建于十多年前的工具库,Lodash的设计和开发是为了解决十多年前 Javascript 开发人员的问题,但很多问题对于现在的我们再也不是问题了。更不用说随着 Typescript 的兴起, 像 Lodash 这样基础的软件包理应提供有用的类型判断。

过时的功能函数

接下来让我介绍一下 Lodash 的一些功能,阐述为什么它们已经过时并不再适合你的项目。

1.png

_.get 函数允许你将字符串或数组值传递给第二个参数,即路径参数。当初这么设计是为了动态匹配更多的参数情况,但现在却可能导致一些错误产生。 比如在 Typescript 中,代码 _.get({ name: 'ray' }, 'age') 是不会产生错误的,因为 Lodash 不会验证对象中是否存在给定的字符串路径。

2.png

这个功能函数存在以下三点问题:

  1. 该函数接受不同类型作为第二个参数,同一个参数类型多样导致了许多不确定的问题。
  2. 当传递对象、数组或字符串时,这些类型不起作用。 由于 Lodash 的类型能力较差,Typescript 无法检查传递的值是否存在于所提供数组的类型上。
  3. 由于空合并可选链的存在,过滤器函数有点过时了。 当空值检查需要多行代码才能安全地执行时,这很有帮助,但现在可以使用 ? 和??实现上图中的任何功能,并且代码更简短。

空值合并
const foo = null ?? 'default value';
console.log(foo); // 输出: 'default value'
可选链
const obj = { foo: { bar: 'value' } };
const value = obj.foo?.bar;

类似的问题还可以在  _.find 和  _.some 函数上看到。

3.png

另外,还有像 _.map 和 _.size 这样的函数,它们不仅具有上述的问题,并且能够接受各种值作为第一个和第二个参数,让使用变得更加复杂。

源码可读性差

如果说上面的那些问题还在我们接受范围内的话,那么 Lodash 源码的学习成本真的很高,因为有时候我们是需要能快速查看源码类协助排查问题的。

这是 Lodash 的一个源码链接,大家可以看一看有多难读了。

如果仅仅是为了了解一个简单的函数实现,就得读成千上万行代码,只能说这个代码写的是真绕!

例如,我想要了解 isString 是如何实现的,我们来看看它有多繁琐:

  1. 首先找到 isString 的定义:
function isString(value) {
  return typeof value == 'string' ||
        (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
}
  1. 接着找到其中使用到的 isObjectLike:
function isObjectLike(value) {
  return value != null && typeof value == 'object';
}
  1. 然后找到其中使用到的 baseGetTag:
function baseGetTag(value) {
      if (value == null) {
        return value === undefined ? undefinedTag : nullTag;
      }
      return (symToStringTag && symToStringTag in Object(value))
        ? getRawTag(value)
        : objectToString(value);
}

可以看到,这里又又又引出了两个新函数 getRawTagobjectToString。这就像无限套娃一样,深不见底!

Radash初识

正因为 Lodash 存在这样那样的问题,社区广大的诉求得不到解决,在这种背景下 Radash 崛起了。

4.png

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 = [123456789]

// 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({ times10 }, api.users.list)
await retry({ times2delay1000 }, api.users.list)

// exponential backoff
await retry({ backoffi => 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(15); // 生成包含 1 到 5 的数字数组
console.log(numbers); // 输出: [1, 2, 3, 4, 5]
  1. 1. 如:指定步长生成数字范围
import { range } from 'radash';

const numbers = range(50-1); // 生成包含从 5 到 0 的递减数字的数组
console.log(numbers); // 输出: [5, 4, 3, 2, 1, 0]

list 函数

功能是创建一个包含指定元素的数组。

  1. 1. 如:创建包含重复元素的数组
import { list } from 'radash';

const repeatedNumbers = list(30); // 创建包含3个重复的数字0的数组
console.log(repeatedNumbers); // 输出: [0, 0, 0]
  1. 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,分享编程经验、技术干货,帮你少走弯路、快速成长。

gzh.png