柯里化是将多参数函数转为单参数链式调用的形式;核心是闭包缓存参数,累计达fn.length时执行,否则返回新函数;需注意fn.length对默认参数和rest参数不准确。

柯里化(Currying)本质是把接收多个参数的函数,转换为每次只接收一个参数、返回新函数的链式调用形式。实现一个通用的参数收集包装器,核心在于:动态记录已传入的参数,直到累积够原函数所需参数个数,再执行原函数。
基础思路:利用闭包缓存参数
每次调用返回的新函数都应记住之前传入的参数,并在参数足够时触发原函数执行。关键点有三个:
- 获取原函数期望的参数个数(fn.length)
- 用数组累积已传入的参数(args)
- 当累积数量 ≥ fn.length,立即执行;否则返回继续接收参数的新函数
简单通用实现(支持不定长初始调用)
以下是一个健壮、可复用的 curry 函数:
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function (...moreArgs) {
return curried.apply(this, args.concat(moreArgs));
};
}
};
}
</font>
<p>使用示例:</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/c1c2c2ed740f" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">Java免费学习笔记(深入)</a></a>”;</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java"><img
src="https://img.php.cn/upload/skill/000/000/081/178955835420587.jpg" alt="Alibabacloud Sdk Client Initialization For Java" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java">Alibabacloud Sdk Client Initialization For Java</a>
<p>在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。</p>
</div>
<a href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div>
<font color="#666">
<pre class="brush:php;toolbar:false;">
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
console.log(curriedAdd(1, 2, 3)); // 6
进阶:支持 this 绑定与占位符(如 _)
真实场景中常需保留调用上下文,或支持“跳过参数”(类似 Lodash 的占位符)。可扩展如下:
- 用 bind 或显式传入 thisArg 保证上下文
- 定义占位符(如 curry.placeholder = {}),遇到它时不计入实参计数
- 收集参数时过滤占位符,但保持位置,最终用实际参数填充空缺
这种增强版更适合封装为工具函数,但基础逻辑不变:参数未满则继续收集,满了就执行。
注意边界:length 不可靠,慎用于箭头函数和 rest 参数
fn.length 只反映非默认、非 rest 的形参个数。例如:
((a, b = 1) => {}).length // 1(b 是默认参数,不计入)
((a, ...rest) => {}).length // 1(rest 不计入)
(() => {}).length // 0
若需完全兼容,建议额外传入期望参数个数 n,或改用显式配置方式收集,而非依赖 length。

















