es-toolkit
本篇范围
本篇聚焦 es-toolkit——2024 年崛起的现代 JavaScript 工具函数库,定位为 Lodash 的高性能、更小体积替代。重点在:相比 lodash 的体积 / 性能优势(用官方数字)、主包 es-toolkit 与兼容层 es-toolkit/compat 的分工、tree-shaking 与 ESM/CJS 双格式、TS-first 的现代 API 设计,以及从 lodash / lodash-es 的迁移路径与取舍。版本基线 es-toolkit 1.49.0。
es-toolkit 是由韩国金融科技公司 Toss 开源的现代 JavaScript 工具库,官方一句话定位是「a modern JavaScript utility library that offers a collection of powerful functions for everyday use」。它覆盖数组、函数、数学、对象、断言(predicate)、Promise、字符串等日常领域,主打相比 lodash 体积最多小约 97%、官方性能总括平均约 2 倍、内置 TypeScript 类型且 100% 测试覆盖。具体函数并非一律更快,选型时应读取基准口径。它已被 Storybook、MUI、Recharts 等成熟项目用于生产。
它的优势源自现代实现:直接用当代 JavaScript 原生 API(Array.prototype、structuredClone、可选链等)重写,抛弃 lodash 为兼容老旧环境而背负的大量内部工具与防御代码——所以单个函数极小(官方实测 sample 约 94 字节、difference 约 90 字节、pick 约 132 字节)。配合 package.json 里的 "sideEffects": false,打包器能把没用到的函数彻底摇掉。
主包 vs 兼容层是理解 es-toolkit 的关键:主包 es-toolkit 只暴露类型安全的现代形态;es-toolkit/compat 则复刻大量 Lodash 函数签名与边界,专供存量项目渐进迁移。官方称 compat 自 v1.39.3 起通过 Lodash 测试套件,但同一份设计说明也把方法链、跨 realm、修改内建原型、部分隐式转换与特化函数列为范围外。因此「先改 import」是降低改造量的起点,不是免测试承诺。新项目应直接用主包;compat 只为迁移而生。
评价
优点
- 体积最多小约 97%:现代原生实现 +
sideEffects:false,单函数可小至不足 100 字节,对被广泛依赖的库尤其能替下游省 bundle - 官方性能总括平均约 2 倍:当前明细基准里
pick约 3.9×、omit约 3.3×,但union与groupBy也存在低于 lodash 的样本 - TS-first:用 TypeScript 编写、内置完整现代类型,无需
@types;许多 predicate(isString/isNil…)还是真正的类型守卫 - 零运行时依赖:dependencies 为空,降低供应链风险、避免依赖膨胀
- ESM + CommonJS 双格式:
exports同时提供import(.mjs)与require(.js),跨 Node 18+ / Deno / Bun / 浏览器 - 现代异步/并发工具:lodash 没有的
Mutex/Semaphore/withTimeout/attempt,以及 debounce/throttle 的AbortSignal集成 - 平滑迁移:
es-toolkit/compat覆盖大量 Lodash API,可先缩小调用点改造范围,再逐步切主包
缺点
- 主包不是 lodash 全集:有意只提供现代核心函数;深路径
get/set等迁移能力在 compat,而 Lodash wrapper 方法链在 compat 也不支持 - compat 有开销:为复刻 Lodash 签名与边界背负额外逻辑,比主包略大、略慢;主包基准不能直接外推到 compat
- 主包 / compat 签名有别:如
pick/omit主包只收键数组、compat 才支持点号深路径与可变参数;从 compat 切主包要逐点核对 - 可变性需分辨:
merge/pull/remove/fill会原地修改入参,不可变场景(Redux/React)要改用toMerged/cloneDeep - 仍在快速迭代:版本已到 1.4x 且持续新增函数,升级应锁版本、关注 changelog
- 仍有明确范围外行为:即便 compat 也不支持 wrapper 方法链、跨 realm / 修改原型等情形,
sortedUniq、sortedUniqBy、mixin、noConflict、runInContext也不在当前导出中