为什么_.curry包装Lodash的_.pick函数后分段传参会报错
问题原因排查
核心报错诱因
Lodash 原生方法的链式包装机制,导致_.curry自动识别的参数数量和你预期的不一致
- 日常使用的
_.pick并不是对应功能的纯函数本体,而是Lodash为了适配链式调用做的一层包装。这层包装的设计目标是从链式上下文中自动获取目标对象,因此它的length属性(代表函数定义时声明的必填形参数量)固定为1,不是你预期的「目标对象、取键数组」两个参数的长度。 _.curry的默认逻辑是读取被包装函数的length属性,确定需要凑够多少个参数才会触发原函数执行。按照这个规则,_.curry(_.pick)生成的柯里化函数,只需要收集到1个参数就会立刻执行原方法,不会等待第二个参数传入。- 对应代码的实际执行流程:
- 执行
_.curry(_.pick)(object)时,因为已经凑够了系统判定需要的1个参数,柯里化函数会立刻调用原_.pick方法。此时因为没有传入第二个参数(需要提取的键数组),pick方法会返回一个空对象。 - 代码拿到这个空对象后,试图将它当作函数传入
['a', 'c']做第二次调用,自然就会抛出_.curry(...)(...) is not a function的TypeError。
- 执行
可落地的修复方式
要让柯里化按照预期的逻辑运行,不需要依赖函数的length属性自动计数,只需要在调用_.curry时显式指定需要收集的参数个数即可:
// 第二个参数显式声明柯里化需要收集2个参数,匹配_.pick的实际功能需求 const curriedPick = _.curry(_.pick, 2); const object = { 'a': 1, 'b': '2', 'c': 3 }; curriedPick(object)(['a', 'c']); // 最终输出和原生_.pick调用完全一致的 { 'a': 1, 'c': 3 }
- 这类参数计数不准的问题,会在所有Lodash原生集合类方法上出现,比如
_.map、_.omit、_.filter等。因为这些方法都做了链式调用适配的包装,自动读取函数长度的柯里化逻辑都会出现计数偏差,手动指定参数数量是通用的解决方式。
内容的提问来源于stack exchange,提问作者Lin Shen
相关产品推荐
相关产品推荐

