又来了一个工具库 es-toolkit - 和 Lodash 对比一下
前端的工具库,最早的热门库为 Underscore,后来 Lodash 逐渐替代 Underscore,成为了主流工具库。Lodash 的灵感来源于 Underscore,在随后的迭代中,Lodash 的功能、兼容性、模块化能力、社区生态都超过了 Underscore,基本是前端项目的工具集标配,除了 Lodash, Ramda 是另外一个比较热门的工具库。
不过 Lodash 的最新版本发布是在三年前,在前端生态喜欢不断推新和 ES 语法每年都有在更新的推动下,新的更现代化工具集库就开始出现了,比如 Radash 和 es-toolkit 等等。Radash 的 1.0.0 版本是在三年前发布,现在已更新到 12.1.0,而 es-toolkit 的第一个版本发布仅仅是两个月前。
Radash 的特点是:
- 它是用 Typescript 编写的
- 源码中使用的语法更加的新
- 提供了一些 Lodash 没有的实用方法(tryit、parallel、retry 等等)
本文主要介绍 es-toolkit 的特点。
es-toolkit 的特点
es-toolkit 的特点有:
- 通过其现代化的实现,es-toolkit 显著减少了其包体积,与 Lodash 等其他库相比,可以减少高达 97%。
- es-toolkit 设计时考虑了性能,与类似 Lodash 的替代库相比,平均性能提升了2倍。
- 全面的运行时支持,除了 Web 和 Node,还支持了 Bun、Deno 运行环境,可以通过 JSR 安装到 Deno。
打包体积
官方给出的相关方法的打包体积数据,可以看到 es-toolkit 打包体积小了很多。

但是你要是实际去看看两边的 API 能力,就会发现这个数据有些水分,从下图就可以看出 Lodash 的 debounce
支持的能力更多。

接着来看下 es-toolkit 的 debounce
源码:
export function debounce<F extends (...args: any[]) => void>(
func: F,
debounceMs: number,
{ signal }: DebounceOptions = {}
): F & { cancel: () => void } {
let timeoutId: number | null = null;
const debounced = function (...args: Parameters<F>) {
if (timeoutId !== null) {
clearTimeout(timeoutId);
}
if (signal?.aborted) {
return;
}
timeoutId = setTimeout(() => {
func(...args);
timeoutId = null;
}, debounceMs) as any;
} as F & { cancel: () => void };
const onAbort = function () {
debounced.cancel();
};
debounced.cancel = function () {
if (timeoutId !== null) {
clearTimeout(timeoutId);
timeoutId = null;
}
};
signal?.addEventListener('abort', onAbort, { once: true });
return debounced;
}
可以看到 es-toolkit 的 debounce
源码相对比较简单,其中 cancel
方法是通过外部传入一个 AbortController
示例来完成的,API 是比较现代化,但是使用上却没有 Lodash 方便。
// lodash cancel debounce
const lodashDeounceFn = lodash.debounce(() => console.log(1), 250);
lodashDeounceFn();
lodashDeounceFn.cancel()
// es-toolkit cancel debouce
const controller = new AbortController();
const signal = controller.signal;
const debouncedWithSignalFunction = debounce(() => console.log(1), 250, { signal });
// 如果在此期间没有再次调用,则在1秒后输出 'Function executed'
debouncedWithSignalFunction();
// 取消了防抖函数的调用
controller.abort();
性能对比
官方给的性能对比数据:

和打包体积类似,虽然 es-toolkit 的 omit
方法性能更高,但是两边支持的能力其实是不太一样的。

Lodash 的 omit
方法可以支持深层的对象属性忽略,而 es-toolkit 只能是第一层属性的忽略。
// es-toolkit 的源码
export function omit<T extends Record<string, any>, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {
const result = { ...obj };
for (const key of keys) {
delete result[key];
}
return result as Omit<T, K>;
}
// es-toolkit 的 omit 的使用
omit({ a: { b: 1 }, c: 2 }, ['a.b', 'c']);
// 返回是 { a: { b: 1 } }
// lodash 的 omit 的使用
lodash.omit({ a: { b: 1 }, c: 2 }, ['a.b', 'c']);
// 返回 { a: {} }
es-toolkit 中的一些方法
flattenObject
扁平化的对象。
const nestedObject = {
a: {
b: {
c: 1
}
},
d: [2, 3]
};
const flattened = flattenObject(nestedObject);
console.log(flattened);
// 输出:
// {
// 'a.b.c': 1,
// 'd.0': 2,
// 'd.1': 3
// }
camelCase
字符串转换为驼峰命名法
import { camelCase } from 'es-toolkit/string';
camelCase('camelCase'); // 返回 'camelCase'
camelCase('some whitespace'); // 返回 'someWhitespace'
camelCase('hyphen-text'); // 返回 'hyphenText'
camelCase('HTTPRequest'); // 返回 'httpRequest'
delay
延迟执行代码指定的毫秒数,支持一个可选的 AbortSignal 来取消延迟。
async function foo() {
const controller = new AbortController();
const signal = controller.signal;
setTimeout(() => controller.abort(), 50); // 在 50 毫秒后取消延迟
try {
await delay(1000, { signal });
} catch (error) {
console.log(error); // 将会输出 'The operation was aborted'
}
}
拓展
无论是 Radash 还是 es-toolkit,提供的 clone
方法都是浅复制,深复制的话就要使用 JS 原生的现代化方法 structuredClone
。不过 structuredClone
不能复制函数和 DOM 节点等等,如果要复制的对象中包括此类属性,方法就会抛出异常,相对来说 Lodash 的复制方法功能更强大,使用也更方便。
const obj = { n: 2 }
const objWithFn = { n: 2, f: () => console.log(1) }
const fn = () => { console.log('fn') }
// lodash
_.cloneDeep(obj) // 返回 { n: 2 }
_.cloneDeep(objWithFn).f() // 输出 1
_.cloneDeep(fn) // 返回 {}
// 原生方法
structuredClone(obj)
// 返回 { n: 2 }
structuredClone(objWithFn)
// Uncaught DOMException: Failed to execute 'structuredClone' on 'Window'
structuredClone(fn)
// Uncaught DOMException: Failed to execute 'structuredClone' on 'Window'
不过你使用 Radash 或者 es-toolkit 的话,也是可以单独安装 Lodash 的 CloneDeep
, 对应包为 lodash.clonedeep
。
总结
es-toolkit 相比与 Lodash 来说,还是有很长一段路要走,毕竟第一个版本是两个月前。不过 es-toolkit 中是有在用更现代化的 API,如果你这些感兴趣,可以参与 es-toolkit 的开源建设。
整体来看,喜欢尝鲜的可以在小项目试试 es-toolkit,其他情况还是建议使用 Lodash,或者可以使用 Radash。
转载自:https://juejin.cn/post/7395022563976904742