柯里化是将多参函数拆为单参函数链,不改逻辑只变调用方式;核心用闭包缓存参数,依fn.length判断执行时机,需正确处理this和剩余参数。

柯里化不是“把函数变复杂”,而是把一个接收多个参数的函数,拆成一系列只接收一个参数的函数。它不改变原函数逻辑,只改变调用方式。
curry 函数怎么写(基础版)
核心是利用闭包保存已传入的参数,直到参数总数满足原函数要求才执行。常见错误是没处理 length 动态变化或箭头函数没有 arguments。
- 用
fn.length获取形参个数,但注意:它只反映函数声明时的参数数量,不包含 rest 参数(...args) - 避免直接依赖
arguments—— 箭头函数没有该对象,应统一用剩余参数...args - 递归返回新函数时,要合并已缓存参数和新传入参数
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
}
return function (...moreArgs) {
return curried.apply(this, args.concat(moreArgs));
};
};
}
为什么 Array.prototype.slice.call 不能直接用在 curry 里
因为 curry 需要支持 this 上下文绑定,而 Array.prototype.slice.call 只处理类数组,不保留调用时的 this。更严重的是,现代代码中大量使用箭头函数或严格模式,arguments 不可靠。
-
fn.apply(this, args)是必须的,确保原函数内部的this正确指向调用者 - 不要用
[].slice.call(arguments),改用Array.from(arguments)或直接用...args - 如果原函数是 class 方法或依赖
this的对象方法,漏掉this绑定会导致undefined报错
实际用例:log、fetch、事件处理器
柯里化真正有用的地方,是提前固化部分配置,让后续调用更简洁。比如日志加前缀、API 基地址、按钮点击行为复用。
立即学习“Java免费学习笔记(深入)”;
-
const logError = curry(console.error).bind(null, '[ERROR]')—— 后续只需logError('user not found') -
const getUser = curry(fetch).bind(null, 'https://api.example.com/')('users/'),但注意:fetch 第二个参数是配置对象,需按实际参数结构设计 curry 层级 - 事件监听中避免重复创建匿名函数:
button.addEventListener('click', curry(handleClick)(userId)),比() => handleClick(userId)更利于内存回收(前提是handleClick本身无闭包泄漏)
柯里化容易被过度设计 —— 如果函数只有两三个参数且调用场景固定,硬套 curry 反而增加理解成本。重点看是否真有“参数分批注入”的需求,而不是为函数式而函数式。









