




柯里化是通过闭包固定部分参数、延迟执行剩余部分的实用机制,非语法糖;核心是fn(a)(b)(c)式分步调用,依赖fn.length判断执行时机,支持多参数传入与this绑定。
curry 不是语法糖,也不是炫技工具——它是你提前“钉住”某些参数、让函数更易复用的实用机制。
curry?它和普通函数调用到底差在哪?简单说:curry 把 fn(a, b, c) 变成可以分步调用的 fn(a)(b)(c),但关键不是“拆写法”,而是“固定一部分、延迟执行剩余部分”。
arguments 临时拼接fn.length 是判断是否该执行的唯一可靠依据(箭头函数没 length,不能直接柯里化)curried(1, 2)(3)),这是工程中真正好用的“非严格柯里化”curry 函数?下面这个版本经实战验证,兼容性好、逻辑清晰、支持 this:
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
}
return (...moreArgs) => curried.apply(this, [...args, ...moreArgs]);
};
}
...args 替代老旧的 arguments,避免箭头函数陷阱curried 的 this,比嵌套 function 更简洁柯里化的价值不在“看起来函数式”,而在解决具体痛点:
const githubApi = curry(fetchApi)('https://api.github.com', 5000),之后所有调用都自带 baseURL 和 timeoutonClick={handleClick(userId)} 比 onClick={() => handleClick(userId)} 更安全,避免每次渲染都新建函数const isEmail = curry((re, str) => re.test(str))(/^[^\s@]+@[^\s@]+\.[^\s@]+$/),生成即用、语义清晰不是所有函数都适合柯里化,尤其要注意:
Math.max、console.log 这类接受任意多参数的函数,柯里化后会破坏直觉(curry(Math.max)(1)(2)(3) ≠ Math.max(1,2,3))(a, b = 10)),fn.length 仍为 2,但实际可能只需传 1 个——这时柯里化行为与预期不符
someFn(x, y, z, ...staticOptions),就该考虑把它交给 curry 了。