资讯动态

es-toolkit/compat 的 unionWith:Lodash 兼容的自定义比较数组并集函数深入解析

发布时间:2026/9/16 22:51:02 来源:尧图企业网站定制
es-toolkit/compat 的 unionWithLodash 兼容的自定义比较数组并集函数深入解析【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkitunionWith是es-toolkit兼容层es-toolkit/compat中与 Lodash 完全对齐的数组工具函数它接受多个数组和一个自定义比较函数合并所有数组并依据该比较函数去重返回只包含唯一值、且保持首次出现顺序的新数组。本文以 docs/ja/compat/reference/array/unionWith.md对应英文版 docs/compat/reference/array/unionWith.md为骨架结合 src/compat/array/unionWith.ts 及其测试用例讲解 API 用法、参数约定、底层实现原理以及它与现代版es-toolkit/array中unionWith的取舍关系。一、先读官方警告compat 版本与现代版本怎么选官方文档在unionWith条目开头即放置了一段醒目的警告warning 提示块这是理解本函数定位的关键请使用es-toolkit的unionWith。此unionWith函数因复杂处理而运行缓慢请改用更快、更现代的es-toolkit的unionWith。这段警告对应的英文原文见 docs/compat/reference/array/unionWith.md 顶部它指向现代版文档 docs/reference/array/unionWith.md。也就是说仓库中存在两套unionWith入口定位签名特点es-toolkit/array现代版面向现代开发的快路径固定接收两个数组 一个比较函数实现于 src/array/unionWith.tses-toolkit/compat本文主角与 Lodash 全兼容的慢路径可变参数...arrays 尾部comparator实现于 src/compat/array/unionWith.ts从源码结构看compat 版本为了兼容 Lodash 的可变参数、null/undefined容忍、类数组对象array-like识别等行为必须先扁平化再逐对比较因此官方文档明确建议能迁移到现代 API 的代码优先使用es-toolkit的unionWith只有需要无缝替换 Lodash 或lodash/fp既有调用时才保留 compat 版本。二、API 总览签名与调用形式const result unionWith(...arrays, comparator);函数接收若干待合并的数组每个参数类型为ArrayLikeT | null | undefined以及一个位于参数末尾的比较函数comparator返回去重后的新数组T[]。对应的 TypeScript 重载定义src/compat/array/unionWith.ts覆盖了从 1 个数组到任意多个数组的调用形态unionWith(arrays, comparator?)unionWith(arrays, arrays2, comparator?)unionWith(arrays, arrays2, arrays3, ...comparator)其中比较函数comparator的签名是(a: T, b: T) boolean返回true表示两个值视为相等后出现的重复值将被剔除返回false表示不相等。三、使用示例从对象、原语到字符串长度1. 自定义比较函数合并对象数组import { unionWith } from es-toolkit/compat; const objects [ { x: 1, y: 2 }, { x: 2, y: 1 }, ]; const others [ { x: 1, y: 1 }, { x: 1, y: 2 }, ]; unionWith(objects, others, (a, b) a.x b.x a.y b.y); // 返回值: [{ x: 1, y: 2 }, { x: 2, y: 1 }, { x: 1, y: 1 }]两个数组都含有{ x: 1, y: 2 }比较函数判定二者相等因此合并结果中只保留先出现的objects[0]。2. 简单等价比较unionWith([1, 2], [2, 3], (a, b) a b); // 返回值: [1, 2, 3]2在两个数组中都出现被判定为重复而只保留一次。3. 以字符串长度为比较依据unionWith([ab, cd], [ef, gh, ab], (a, b) a.length b.length); // 返回值: [ab]ab、cd、ef、gh长度均为 2彼此视为相等因此首个元素ab保留其余全部被剔除。这个例子直观说明了comparator并不要求是真正的等价关系任何自定义判定逻辑都可以生效。4.null/undefined数组会被忽略import { unionWith } from es-toolkit/compat; unionWith([1, 2], null, undefined, [3, 4], (a, b) a b); // 返回值: [1, 2, 3, 4]这是与 Lodash 对齐的宽容行为混入null或undefined不会抛错而是被静默跳过。四、参数与返回值说明参数...arraysArrayArrayLikeT | null | undefined要合并的数组。支持普通数组也接受类数组对象array-likenull与undefined会被忽略。comparator(a: T, b: T) boolean判断两个值是否相等的比较函数。返回值T[]使用比较函数去重后的唯一值组成的新数组各值保持首次出现顺序。原数组不会被修改。五、源码级原理从可变参数到去重结果的完整调用链unionWith的实现非常精简核心逻辑全部收敛在 src/compat/array/unionWith.tsexport function unionWithT(...values: ArrayArrayLikeT | null | undefined | ((a: T, b: T) boolean)): T[] { const lastValue last(values); const flattened flattenArrayLike(values as ArrayArrayLikeT); if (isArrayLikeObject(lastValue) || lastValue null) { return uniq(flattened); } return uniqWith(flattened, lastValue); }整个调用链可以分为三步第 1 步取出末尾比较函数。使用last(values)取得最后一个参数。如果最后一个参数是类数组对象或null/undefined说明调用方没有传入比较函数例如unionWith([2], [1, 2])此时退化为普通union语义。第 2 步扁平化所有类数组参数。flattenArrayLike实现见 src/compat/_internal/flattenArrayLike.ts遍历每个参数仅对通过isArrayLikeObject校验的值展开其元素null、undefined、数字、普通对象等非类数组参数被直接跳过——这正是忽略null/undefined数组行为以及测试中忽略非数组值行为的来源。同时它只做一层展开因此嵌套数组[1, [5]]中的[5]会作为整体元素保留不会被深度扁平化对应测试should not flatten nested arrays见 src/compat/array/unionWith.spec.ts。第 3 步分两条路径去重。没有比较函数时调用uniqsrc/array/uniq.ts内部直接[...new Set(arr)]走 O(n) 的快速路径有比较函数时调用uniqWithsrc/array/uniqWith.ts对每个元素与结果数组中已有元素逐一调用comparator比对只有从未与任何已保留元素相等时才推入结果数组。由于要两两比较这部分的时间复杂度为 O(n²)这正是官方警告复杂处理导致运行缓慢的根本原因。此外uniqWith的实现保证了重复值保留第一次出现的那个——测试should output values from the first possible arraysrc/compat/array/unionWith.spec.ts验证了当objects [{ x: 1, y: 1 }]、others [{ x: 1, y: 2 }]且比较函数只看x时结果保留的是来自第一个数组的{ x: 1, y: 1 }。六、行为细节与 Lodash 兼容性边界unionWith的测试直接以 Lodash 的union-methods.spec.js、unionWith.spec.js为参照见 src/compat/array/unionWith.spec.ts可确认以下兼容行为多数组合并unionWith([2], [1, 2], [2, 3])返回[2, 1, 3]与 Lodash 一致不深扁平化unionWith([1, 3, 2], [1, [5]], [2, [4]])返回[1, 3, 2, [5], [4]]忽略非数组参数unionWith(array, 3, { 0: 1 }, null)中数字、普通对象、null均被忽略支持 arguments 对象测试中argsarguments对象定义见 src/compat/_internal/args.ts被当作合法类数组参与合并与isEqual组合unionWith(objects, others, isEqual)可实现对对象内容的深比较去重isEqual来自 src/predicate。七、对比compat 版与现代版的差异速查现代版 src/array/unionWith.ts 的实现是export function unionWithT( arr1: readonly T[], arr2: readonly T[], areItemsEqual: (item1: T, item2: T) boolean ): T[] { return uniqWith(arr1.concat(arr2), areItemsEqual); }两者核心差异归纳如下维度es-toolkit/compat版es-toolkit/array版参数形态可变参数...arrays 末尾comparator固定两个数组 第三个比较参数数组数量任意多个恰好两个null/undefined容忍支持自动忽略不支持按普通值处理类数组对象支持ArrayLike仅接受readonly T[]省略比较函数退化为uniqunion语义编译期强制必传实现开销先flattenArrayLike再uniqWith整体 O(n²)直接concatuniqWith同样 O(n²) 但少一层封装结论很明确新代码优先从es-toolkit/array导入unionWith只有迁移 Lodash 存量代码、且依赖忽略空参数/多数组/类数组等兼容语义时才从es-toolkit/compat导入。官方警告中的更快更现代指的就是前者。【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价