柯里化是将多参函数转为单参函数链的过程,核心是固定部分参数并返回新函数等待剩余参数。其实现依赖闭包与递归判断参数数量,典型场景包括预设配置、配合React Hooks及函数式组合,但需注意fn.length局限、区别于偏函数,并避免过度使用。

函数柯里化(Currying)是将一个接收多个参数的函数,转换为一系列只接收单个参数的函数链的过程。核心不是“拆参数”,而是“固定一部分参数,返回新函数等待剩余参数”,从而实现参数的逐步求值和复用。
如何手动实现柯里化
最基础的手动实现依赖闭包和递归判断参数数量:
示例(通用版):
function curry(fn) {return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function(...nextArgs) {
return curried.apply(this, args.concat(nextArgs));
};
}
};
}
使用方式:
立即学习“Java免费学习笔记(深入)”;
const add = (a, b, c) => a + b + c;const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6
console.log(curriedAdd(1)(2, 3)); // 6
柯里化在实际开发中的典型场景
-
预设配置,提升可读性:比如封装带默认前缀的日志函数。
const logWithPrefix = curry((prefix, level, msg) => console[level](`[${prefix}] ${msg}`));
const errorLog = logWithPrefix('API');
errorLog('error', 'Request failed'); -
与高阶组件或 hooks 配合:React 中常用于生成定制化 Hook。
const useFetch = curry((baseUrl, options) => () => fetch(`${baseUrl}/data`, options));
const useUserApi = useFetch('/api/users');
const data = useUserApi({ method: 'GET' }); -
函数式编程组合(compose / pipe)的基础:只有单参数函数才能无缝串联。
const map = curry((fn, arr) => arr.map(fn));
const filter = curry((pred, arr) => arr.filter(pred));
const doubleOdds = compose(map(x => x * 2), filter(x => x % 2 === 1));
doubleOdds([1, 2, 3, 4]); // [2, 6]
注意边界与常见误区
- JavaScript 的
fn.length只反映形参个数,不处理 rest 参数(...args)——遇到含 rest 的函数需额外约定或改用显式参数数指定。 - 柯里化 ≠ 偏函数(Partial Application):偏函数可固定任意参数、返回接受剩余参数的函数;柯里化严格按顺序逐个收参,且每次只收一个。
- 过度柯里化会增加调用开销和理解成本,适合配置类、工具类函数,不适合高频简单计算(如
Math.max)。
现代替代方案参考
ES6+ 中部分场景可用解构 + 默认值替代简易柯里化:
const createButton = ({ type = 'button', size = 'md', disabled = false } = {}) =>`
但当需要动态组合、延迟执行或融入函数式流水线时,柯里化仍有不可替代的价值。










