柯里化函数需通过闭包保存参数并动态判断是否满足fn.length,支持多层调用;类型判断应基于object.prototype.tostring.call并封装为可扩展的柯里化谓词函数。

curry 函数怎么写才支持多层嵌套调用
柯里化不是简单地把参数拆开,关键在「返回新函数时,要能判断是否已收集够参数」。常见错误是硬编码参数个数,导致 isString() 和 isString('abc') 都得走同一套逻辑,结果后者直接返回 boolean,前者却返回函数,调用链就断了。
实操建议:
- 用闭包保存已传参数,每次调用都检查
arguments.length >= fn.length(注意:箭头函数没length,得用普通函数) - 不要用
rest参数重写原函数签名,否则fn.length变成 0,判断失效 - 若目标函数有默认参数,
fn.length不包含它们,这点容易被忽略
示例:function curry(fn) { return function curried(...args) { if (args.length >= fn.length) return fn(...args); return (...more) => curried(...args, ...more); }; }
type-checking 工具函数为什么要先 curry 再封装 isXxx
不柯里化的 isString(val) 每次都要传完整参数,没法复用;而柯里化后,isString 本身是函数,可直接用于 array.filter(isString) 或 map(isNumber),这才是通用性的来源。
实操建议:
- 把类型判断逻辑抽成纯函数,如
function isString(x) { return typeof x === 'string'; } - 用上面的
curry包一层,得到const isString = curry(function(x) { return typeof x === 'string'; }); - 这样
isString('a')返回true,isString单独用就是谓词函数,无需额外包装
常见错误:有人写 const isString = () => x => typeof x === 'string',看似柯里化,但丢失了「可直接执行」的能力——isString('a') 会报错,因为第一层没参数可接。
为什么 Object.prototype.toString.call 比 typeof 更可靠
typeof null 返回 "object",typeof [] 也是 "object",根本分不清数组、正则、日期。而 Object.prototype.toString.call(x) 能返回 "[object Array]" 这类标准字符串,才是类型判断的底层依据。
实操建议:
- 统一用
Object.prototype.toString.call(x).slice(8, -1).toLowerCase()提取类型名 - 柯里化时,把这个提取逻辑封装进基础函数,比如
function getType(x) { return Object.prototype.toString.call(x).slice(8, -1).toLowerCase(); } - 再基于
getType柯里化出isArray、isDate等,避免每个都重复写call和slice
性能提示:虽然 toString.call 比 typeof 稍慢,但现代引擎优化得很好,类型工具函数本就不该是性能瓶颈;可靠性远比这点开销重要。
如何让 isXxx 函数支持自定义类型名或 Symbol 类型
原生 toString 对自定义类或 Symbol 返回固定字符串(如 "[object Symbol]"),但有些场景需要识别 isPromise 或 isMyCustomClass,这就得手动扩展。
实操建议:
- 给柯里化后的基础判断函数加一个「注册表」,比如
addType('promise', x => x && typeof x.then === 'function') - 在
getType之后先查注册表,命中就直接返回,不命中再走toString.call - 注意
Symbol类型不能用instanceof,得用typeof x === 'symbol'判断
容易踩的坑:注册逻辑如果放在柯里化函数内部,每次调用都会新建闭包,注册信息无法共享;必须把注册表提到外层作用域,或者用模块级变量维护。
真正难的不是写出 curry,而是让每个 isXxx 在「单独调用」「作为回调」「支持扩展」这三件事上都不掉链子。多数人卡在第二步——以为柯里化只是语法糖,其实它是让函数具备上下文适应能力的关键设计。










