es-toolkitunary使用指南:限制函数最多接收一个参数(Lodash 兼容实现)
【免费下载链接】es-toolkitA modern JavaScript utility library that's 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit
unary是es-toolkit/compat(Lodash 兼容模块)提供的一个函数工具,它将目标函数包装为最多只接收一个参数的新函数,超出部分会被静默忽略。它的典型应用场景是配合Array.prototype.map这类会向回调传递多余参数的高阶方法,解决parseInt被传入索引参数而返回NaN这类经典问题。读完本文你将掌握unary的调用方式、参数与返回值语义、与ary的关系,以及它在源码层面的实现原理。
概览:一行代码锁定参数个数
const limitedFunc = unary(func);与 Lodash 的unary完全对齐,es-toolkit的兼容版unary(func)返回一个新函数,该函数调用原始func时只透传第一个参数,其余参数一律丢弃。
import { unary } from 'es-toolkit/compat';注意:该函数位于
compat入口,用于 Lodash 兼容场景;现代es-toolkit主入口同样提供unary,两者的行为一致(见下文源码分析)。
使用方式:unary(func)
当你想让一个函数"最多只接收一个参数"时,就用unary包装它。任何额外传入的参数都会被忽略。
基础示例:截断多余参数
import { unary } from 'es-toolkit/compat'; function greet(name, greeting, punctuation) { return `${greeting} ${name}${punctuation}`; } // 转换为只接收第一个参数的函数 const greetOne = unary(greet); greetOne('Alice', 'Hello', '!'); // 等价于 greet('Alice'),返回 'undefined Aliceundefined'这里greetOne内部只会把'Alice'传给greet,'Hello'与'!'被丢弃,因此greeting与punctuation均为undefined。
实战场景:修复map(parseInt)的经典陷阱
unary最常见的用途是与数组的map方法配合。Array.prototype.map会向回调传递三个参数(当前元素、索引、整个数组),而parseInt本身接收两个参数(字符串与进制基数),二者叠加会产生意想不到的结果:
const numbers = ['1', '2', '3']; numbers.map(parseInt); // [1, NaN, NaN] —— 意外结果 // 实际执行的是 parseInt('2', 1)、parseInt('3', 2),进制非法导致 NaN numbers.map(unary(parseInt)); // [1, 2, 3] —— 正确结果 // 索引与数组参数被丢弃,parseInt 只拿到字符串,默认按十进制解析这正是"截断回调多余参数"这一模式的经典应用,也解释了为什么函数式编程中常常需要对回调做参数限制。
参数与返回值
func((...args: any[]) => any):需要限制参数个数的目标函数。- 返回值(
(...args: any[]) => any):一个新的函数,最多只接收一个参数。
注意,unary不会强制最小参数数量:即使调用返回函数时不传任何参数,它也会正常执行(传入空参数列表),这一点在源码测试中有明确覆盖。
源码实现:unary是ary的特例
es-toolkit的兼容版unary实现极为精简,位于 src/compat/function/unary.ts,其核心只有一行:
import { ary } from './ary.ts'; export function unary<T, U>(func: (arg1: T, ...args: any[]) => U): (arg1: T) => U { return ary(func, 1); }即:unary(func)等价于ary(func, 1),也就是把参数上限固定为 1 的ary调用。
继续追踪调用链,兼容版的ary位于 src/compat/function/ary.ts,它负责处理参数校验与默认值后,转交给主入口的 src/function/ary.ts 完成真正的截断逻辑:
// src/compat/function/ary.ts(节选) if (Number.isNaN(n) || n < 0) { n = 0; } return aryToolkit(func, n);// src/function/ary.ts(节选) export function ary<F extends (...args: any[]) => any>(func: F, n: number): (...args: any[]) => ReturnType<F> { return function (this: any, ...args: Parameters<F>) { return func.apply(this, args.slice(0, n)); }; }可以看到底层机制非常简单:包装函数通过args.slice(0, n)只保留前n个参数,再用func.apply(this, ...)调用原函数——this绑定被完整保留(这在测试中有专门用例验证,见 src/compat/function/unary.spec.ts)。unary场景下n = 1,因此slice(0, 1)恰好只留下第一个参数。
为什么文档建议优先使用ary
原文档(docs/ja/compat/reference/function/unary.md)明确给出警告:由于unary只是ary的特殊情况,当需要更多控制(例如限制为 2 个、3 个参数或 0 个参数)时,应直接使用现代es-toolkit的ary,例如:
import { ary } from 'es-toolkit/function'; // 限制为 0 个参数 ary(fn, 0)(1, 2, 3); // [] // 限制为 2 个参数 ary(fn, 2)(1, 2, 3); // [1, 2]详细用法可参考 ary 官方文档 与 兼容版 ary 文档。此外,兼容版ary还支持省略n时默认取func.length,并带有参数校验(负数或NaN归零)与 lodash 风格的guard保护逻辑,灵活性远超固定为 1 的unary。
测试验证:三个关键行为
仓库中的单元测试 src/compat/function/unary.spec.ts 使用 Vitest 编写,覆盖了unary的三个核心契约:
- 截断多余参数:
map(['6', '8', '10'], unary(parseInt))的结果为[6, 8, 10],验证了与map配合时的正确行为; - 不强制最小参数个数:
unary(fn)()不传任何参数也能正常调用并返回[]; - 保留
this绑定:将包装后的函数作为对象方法调用时,this正确指向该对象。
这三条用例从行为层面对应了上文源码中的slice(0, 1)与func.apply(this, ...)实现,可作为你理解与验证unary语义的直接依据。
小结
unary(func)返回一个最多接收一个参数的新函数,多余参数被忽略;- 经典用法是配合
map等会传递多余参数的高阶方法,修复parseInt的NaN陷阱; - 源码层面
unary即ary(func, 1),底层通过args.slice(0, n)+func.apply(this, ...)实现; - 需要更灵活的参数上限控制时,建议改用功能更全的
ary。
【免费下载链接】es-toolkitA modern JavaScript utility library that's 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考