柯里化
柯里化(Currying)是函数式编程中的一种高阶技术,其核心思想是将一个接受多个参数的函数转换为一系列接受单一参数的函数链,每个新函数返回处理剩余参数的新函数,直到所有参数收集完毕并最终执行原函数。以下是其核心要点:
一、柯里化的核心原理
-
参数逐步收集 柯里化函数通过闭包保存已传入的参数,并逐步收集剩余参数。例如:
// 原函数:接受3个参数
const add = (a, b, c) => a + b + c;
// 柯里化后
const curriedAdd = a => b => c => add(a, b, c);
console.log(curriedAdd(1)(2)(3)); // 6每次调用返回一个新函数,直到所有参数满足原函数的要求。
-
闭包与递归实现 柯里化的实现依赖闭包保存中间状态,并通过递归或条件判断参数是否足够。例如:
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn(...args);
} else {
return (...nextArgs) => curried(...args, ...nextArgs);
}
};
}
二、柯里化的典型应用场景
-
参数复用 固定部分参数生成新函数,减少重复代码。例如:
const sumCurry = a => b => a + b;
const add5 = sumCurry(5); // 固定第一个参数
add5(3); // 8(复用a=5) -
延迟执行 分批次传入参数,直到满足条件才触发计算。例如:
const logTime = level => message => console.log(`[${level}] ${message}`);
const errorLog = logTime("ERROR"); // 先固定日志级别
errorLog("File not found"); // 延迟执行输出 -
提前计算与兼容处理 在一次判断后生成特定逻辑的函数,避免重复判断。例如:
const useEvent = () => {
if (window.addEventListener) {
return (el, type, fn) => el.addEventListener(type, fn);
} else {
return (el, type, fn) => el.attachEvent("on" + type, fn);
}
};
const addEvent = useEvent(); // 提前确定兼容性方案 -
函数组合 柯里化支持将多个函数组合成新函数。例如:
const prop = key => obj => obj[key];
const getNames = users => users.map(prop("name"));
三、柯里化的优缺点
优点 | 缺点 |
---|---|
提高代码复用性 | 增加代码复杂度 |
支持灵活的参数传递 | 闭包可能引发内存泄漏 |
便于函数组合与抽象 | 性能略低于普通函数 |
四、与其他概念的区别
-
偏函数(Partial Application) 偏函 数是固定部分参数后生成的中间函数,而柯里化是逐参数拆分的过程。
// 偏函数示例(固定一个参数)
const addPartial = (a, b) => c => a + b + c; -
闭包(Closure) 柯里化依赖闭包保存中间参数,但闭包本身是更广泛的概念(函数访问外部作用域的能力)。
五、总结
柯里化的本质是参数的分治策略,通过拆分多参数函数,提升代码的灵活性与复用性。它在函数式编程、参数校验、延迟计算等场景中广泛应用。但需注意其可能带来的复杂性和性能影响,合理权衡使用场景。