es-toolkit 函数式编程指南:使用 fp.at 在 pipe 管道中按索引取值
发布时间:2026/9/16 15:47:04 作者:尧图编辑部 阅读量:1,286

es-toolkit 函数式编程指南使用 fp.at 在 pipe 管道中按索引取值【免费下载链接】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导读at是 es-toolkit 数组工具中用于按索引批量取值的函数而其函数式编程变体fp.at则把这一能力包装成数据后置data-last的管道算子让它可以与pipe无缝组合。本文以 docs/fp/reference/at.md 为骨架结合 fp 实现源码、基础数组实现 与 pipe 惰性求值机制讲解fp.at的用法、参数语义、底层原理以及它和普通at的取舍关系。一、fp.at是什么在 es-toolkit 的函数式编程入口es-toolkit/fp中所有函数都遵循先传配置后传数据的柯里化约定。fp.at正是这样的一个算子import { at, pipe } from es-toolkit/fp; const result pipe(array, at(indices));它的核心语义是创建一个函数该函数从被管道传入的数组中按给定的索引列表取出对应位置的值。与普通写法at(arr, indices)相比fp.at把数组参数挪到了最后从而可以被pipe以自顶向下的顺序串起来执行。二、基本用法文档给出的最小示例即展示了完整用法见 docs/fp/reference/at.mdimport { at, pipe } from es-toolkit/fp; pipe([a, b, c], at([0, -1])); // [a, c]执行过程可以拆解为两步at([0, -1])返回一个等待数据的函数类型为(array: readonly T[]) T[]pipe将数组[a, b, c]作为数据喂给该函数得到[a, c]。这正是 fp/intro.md 中描述的 fp 入口的设计哲学每个es-toolkit/fp函数先用配置参数这里是indices构造一个算子再由pipe提供数据把上一步的输出作为下一步的输入。参数与返回值项说明indicesnumber[]或readonly number[]要从被管道传入的数组中读取的索引列表返回值(array: readonly T[]) T[]一个把readonly T[]映射为所选值新数组的函数负索引语义at从被管道传入的数组中的每个索引读取值。负索引从数组末尾倒数行为与Array.prototype.at一致。例如pipe([a, b, c], at([0, -1])); // [a, c] // 索引 0 取 a索引 -1 从末尾倒数取 c三、底层实现一层薄薄的柯里化包装从源码结构看fp.at本身非常轻量它并不重复实现取值逻辑而是直接复用了 es-toolkit 基础版的at见 src/fp/array/at.tsimport { at as atToolkit } from ../../array/at.ts; export function atT(indices: readonly number[]): (array: readonly T[]) T[] { return function (array: readonly T[]): T[] { return atToolkit(array, indices); }; }关键点在于fp 变体只改变调用形态不改变算法。indices在算子创建时被闭包捕获等到pipe把数组传入时才真正调用基础版at(arr, indices)。这与 fp/intro.md 中es-toolkit/fp复用es-toolkit的实现只改变调用方式的说明完全吻合。在 src/fp/array/index.ts 中at通过export { at } from ./at.ts;被统一导出因此可以从es-toolkit/fp顶层直接导入。基础版at的取值逻辑被复用的基础实现位于 src/array/at.tsexport function atT(arr: readonly T[], indices: readonly number[]): T[] { const result new ArrayT(indices.length); const length arr.length; for (let i 0; i indices.length; i) { let index indices[i]; index Number.isInteger(index) ? index : Math.trunc(index) || 0; if (index 0) { index length; } result[i] arr[index]; } return result; }从实现可以提炼出几个值得注意的细节返回新数组不修改原数组结果数组长度与indices.length一致按索引顺序排列如[2, 0]会得到[c, a]而非按原数组顺序。非整数索引会被转换为整数使用Number.isInteger判断非整数走Math.trunc(index) || 0即向零取整1.5变为12.9变为2NaN、0等被规整为0。这一点在 docs/reference/array/at.md 中也有相应示例。负索引处理负索引加上数组长度得到真实位置-1对应最后一个元素。越界索引返回undefined基础实现的测试用例src/array/at.spec.ts覆盖了at([a, b, c], [2, 4, 0, -4])得到[c, undefined, a, undefined]的行为即超出范围时对应位置为undefined。测试佐证fp.at的专项测试位于 src/fp/array/at.spec.ts验证了它在管道中的实际工作方式import { describe, expect, it } from vitest; import { at } from ./at.ts; import { pipe } from ../pipe.ts; describe(at, () { it(works in a pipe, () { expect(pipe([a, b, c], at([0, -1]))).toEqual([a, c]); }); });这组测试同时印证了两点fp.at从es-toolkit/fp子路径导出可用且必须配合pipe使用才能拿到数据。四、与普通at的关系何时用哪个文档在info提示块中给出了明确的使用建议见 docs/fp/reference/at.md在普通代码中优先使用 es-toolkit 原始版的at只有在用pipe组合变换时才使用这个fp变体。两条路线的对比场景推荐写法示例直接、一次性的取值基础版atat([a, b, c, d], [0, -1, -2])→[a, d, c]在变换管道中组合fp 版atpipe(data, at([0, -1]), map(fn))基础版at的完整文档见 docs/reference/array/at.md签名是at(arr, indices)参数含义为arrreadonly T[]被取值的数组和indicesreadonly number[]取值索引负值从末尾计数返回T[]新数组。五、在 pipe 管道中组合与惰性求值的关系fp.at的价值在于它处在pipe构建的变换链中。pipe的实现位于 src/fp/pipe.ts它支持最多 15 个函数的从左到右组合并实现了**惰性融合lazy fusion**优化当连续的惰性算子如map、filter、take相邻时pipe会把它们融合成单趟遍历每个元素一次性穿过所有步骤不再在步骤之间构造中间数组遇到take等短路算子还会提前终止遍历。需要说明的是从源码结构看fp.at本身是一个普通非惰性算子——它直接调用基础版at并立即返回新数组。因此它天然适合放在管道中靠近数据端的位置先按索引取子集再做后续变换而不是像map/filter那样参与惰性融合。一个典型的组合示例import { at, map, pipe } from es-toolkit/fp; // 先取出第 1、3、-1 个元素再对它们做变换 pipe( [10, 20, 30, 40, 50], at([1, 3, -1]), // [20, 40, 50] map(x x * 2) // [40, 80, 100] );得益于 contenteditable="false">【免费下载链接】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),仅供参考