ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

es-toolkit/compat 的 rearg 函数:按索引重排函数参数的完整指南

es-toolkit/compat 的 rearg 函数:按索引重排函数参数的完整指南 es-toolkit/compat 的 rearg 函数按索引重排函数参数的完整指南【免费下载链接】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导读rearg是 es-toolkit 兼容层es-toolkit/compat中用于重排函数调用参数顺序的高阶函数它根据你指定的索引序列生成一个新函数新函数在调用时会先把实参按索引重排再传给原函数执行。本文围绕 docs/compat/reference/function/rearg.md 展开结合 rearg.ts 源码与 rearg.spec.ts 测试用例讲解参数形式、边界行为、实现原理以及何时应该避免使用它。读完你将能熟练运用rearg适配第三方回调签名并理解其与 Lodash 行为对齐的细节。适用前提本文示例均基于当前仓库es-toolkit 的compat兼容层导入路径为es-toolkit/compat。该兼容层的定位是 1:1 镜像 Lodash 的接口与行为便于存量 Lodash 代码平滑迁移详见 docs/compat/intro.md。基本用法rearg(func, ...indices)rearg创建一个新函数该函数会按照indices指定的顺序重排调用时的实参再调用原函数。官方文档给出的签名如下const rearranged rearg(func, ...indices);最典型的场景是交换前两个参数的顺序import { rearg } from es-toolkit/compat; const greet (greeting, name) ${greeting}, ${name}!; // Swap argument order (1st, 0th) const rearrangedGreet rearg(greet, 1, 0); rearrangedGreet(World, Hello); // Returns: Hello, World! // Original function remains unchanged greet(Hello, World); // Returns: Hello, World!注意rearg返回的是新函数原函数greet不会被修改其调用语义完全不变。参数与返回值func(...args: any[]) any需要重排参数的原函数。...indicesArraynumber | number[]要重排的参数索引序列支持嵌套数组。返回值(...args: any[]) any一个实参已按索引重排的新函数。支持数组形式传入索引除了逐个传入索引你也可以把索引打包成一个数组import { rearg } from es-toolkit/compat; const fn (a, b, c) [a, b, c]; // Specify indices using an array const rearranged rearg(fn, [2, 0, 1]); rearranged(a, b, c); // Returns: [c, a, b]索引[2, 0, 1]的含义是新函数接收的实参中第 2 个参数作为新函数的第 1 个参数传入原函数第 0 个参数作为新函数的第 2 个参数第 1 个参数作为第 3 个参数。测试用例 rearg.spec.ts 中的should accept multiple arrays of indexes还验证了rearg(fn, [2], [0, 1])这种多个数组参数的写法同样有效。部分重排只调整部分参数索引序列的长度可以小于实参个数未涉及的参数保持原有位置import { rearg } from es-toolkit/compat; const fn (a, b, c, d) [a, b, c, d]; // Rearrange only the first two arguments const rearranged rearg(fn, 1, 0); rearranged(first, second, third, fourth); // Returns: [second, first, third, fourth]这里的机制是索引序列只覆盖前两个参数的位置剩余参数third、fourth按原顺序追加到末尾。对应测试用例should work with fewer indexes than argumentsrearg(fn, [1, 0])后rearged(b, a, c)返回[a, b, c]验证了这一行为。边界行为不存在的索引与非法索引不存在的索引视为undefined如果索引超出了实参的个数该位置将被填充为undefinedimport { rearg } from es-toolkit/compat; const fn (a, b, c) [a, b, c]; // Include non-existent index 5 const rearranged rearg(fn, 5, 1, 0); rearranged(a, b, c); // Returns: [undefined, b, a]非法索引值同样得到undefined测试用例should use undefined for non-index values对[{}, null, undefined, false, NaN, , -1, 1.1]这一组非法索引逐一验证结果均为[undefined, b, c]——即第一个位置为undefined其余参数保持原样。这说明rearg并不做索引合法性校验而是依赖 JavaScript 数组下标越界时天然返回undefined的特性。不传任何索引时参数顺序不变测试用例should not rearrange arguments when no indexes are given验证rearg(fn)或rearg(fn, [], [])之后实参原样传递。嵌套数组索引会被拍平处理索引参数支持嵌套数组rearg会将其扁平化后再使用import { rearg } from es-toolkit/compat; const fn (a, b, c, d) [a, b, c, d]; // Nested array indices const rearranged rearg(fn, [1, [2, 0]], 3); rearranged(a, b, c, d); // Returns: [b, c, a, d]等价于展开为索引序列[1, 2, 0, 3]即原实参的b、c、a、d依次成为新函数的四个参数。重复索引也是合法的测试用例should work with repeated indexes显示索引可以重复使用rearg(fn, [1, 1, 1])作用于rearged(c, a, b)会返回[a, a, a]即同一个实参可以被重排到多个位置。源码级解析rearg 的实现原理rearg在 src/compat/function/rearg.ts 中的实现非常精简核心逻辑如下为便于阅读已简化注释export function rearg( func: (...args: any[]) any, ...indices: ArrayManynumber ): (...args: any[]) any { const flattenIndices flatten(indices); return function (this: any, ...args: any[]) { const reorderedArgs: any[] flattenIndices.map(i args[i]).slice(0, args.length); for (let i reorderedArgs.length; i args.length; i) { reorderedArgs.push(args[i]); } return func.apply(this, reorderedArgs); }; }整个执行流程可以拆解为三步索引拍平创建期indices的类型是ArrayManynumber其中ManyT定义于 src/compat/_internal/Many.ts即T | readonly T[]。flatten来自 src/compat/array/flatten.ts它会基于flattenDepth(..., 1)把嵌套数组拍平一层得到一维索引数组flattenIndices。这是嵌套数组索引支持的底层来源。按索引重排调用期每次调用新函数时通过flattenIndices.map(i args[i])按索引取实参。由于flattenIndices是预先计算并缓存在闭包中的每次调用不会重复拍平索引这是性能上的一个细节。索引越界时args[i]为undefined这正是上述边界行为的实现基础同时.slice(0, args.length)截断到实参个数避免产生多余的undefined。补全剩余实参reorderedArgs长度不足实参个数时循环把剩余实参原样追加实现部分重排。最后通过func.apply(this, reorderedArgs)调用原函数并保留调用方this上下文因此rearg包装后的函数仍然可以作为对象方法使用。一个值得注意的组合特性测试用例should work on functions that have been rearged验证了rearg可以叠加使用rearg(rearg(fn, 2, 1, 0), 1, 0, 2)仍然得到正确结果。由于每次rearg返回的都是普通函数多层包装在行为上等价于多次参数映射的组合。实际应用场景与迁移定位rearg的典型用途包括适配第三方回调签名当库的回调参数顺序与你的函数不一致时无需改写业务函数用rearg做一层薄包装即可。复用 Lodash 存量代码es-toolkit/compat的存在意义就是让旧代码无痛迁移。rearg在 src/compat/compat.ts 中被导出可以从es-toolkit/compat统一导入也可以按需单独导入对应入口详见 docs/compat/intro.md 关于单函数导入的说明。需要说明的是根据 docs/compat/intro.md 的设计原则es-toolkit/compat只保证与 Lodash 的行为与测试用例对齐并不包含方法链式调用等超出其范围的能力rearg同样遵循这一边界。重要建议优先使用箭头函数官方文档在开篇就以醒目的警告框提示rearg创建的是一个重排参数的复杂包装器可能存在性能开销。对于多数场景直接用箭头函数手动重排参数会更清晰、更快速// 不推荐为了理解代码还需额外心智负担 const rearrangedGreet rearg(greet, 1, 0); // 推荐箭头函数直接重排 const rearrangedGreet (name, greeting) greet(greeting, name);因此rearg更适合作为迁移 Lodash 存量代码时的过渡方案或在参数位置确实需要动态配置索引序列来自运行时数据的场景下使用新代码优先考虑箭头函数。这也是 es-toolkit 兼容层的一贯哲学compat保留与 Lodash 完全一致的行为以方便迁移而严格 APIes-toolkit主入口只暴露类型安全、更现代的写法。小结rearg(func, ...indices)的核心要点可以归纳如下行为说明基本用法按索引序列重排实参后调用原函数返回新函数原函数不变索引形式支持rearg(fn, 2, 0, 1)与rearg(fn, [2, 0, 1])也支持多个数组参数嵌套数组索引数组会被拍平对应flatten实现部分重排索引个数少于实参个数时剩余实参按原顺序追加越界 / 非法索引结果为undefined不会抛错重复索引允许同一实参可被映射到多个位置this传递通过func.apply(this, ...)保留调用方上下文性能建议包装器有额外开销新代码优先使用箭头函数手动重排如果你想深入验证上述行为可以直接运行 rearg.spec.ts 中的全部测试用例它们覆盖了本文讨论的每一种边界情况。【免费下载链接】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),仅供参考
返回列表