如何在JavaScript中创建可中途复用的无限柯里化函数?
无限柯里化函数的复用问题解决
问题场景
你实现的无限柯里化函数在基础累加场景正常,但复用中途生成的函数时,会累积之前的结果,不符合预期:
// 原实现代码 function infiniteCurry(fn, startValue) { return function (n) { let acc = startValue; function helper(n) { if (n != undefined) { acc = fn(acc, n); return helper; } else return acc; } return helper(n); } } function sum(a, b) { return a + b; } const curriedSum = infiniteCurry(sum, 0); // 基础场景正常 console.log(curriedSum(1)(2)(3)() == 6); // true // 复用中途函数出现问题 const add1 = curriedSum(1); console.log(add1(4)() == 5); // true console.log(add1(4)() == 9); // true,不符合预期,应该还是5
这是柯里化函数的常规表现吗?
不是。柯里化的核心是将多参数函数拆解为一系列单参数函数,纯柯里化函数应该是无状态的——每次调用生成的新函数,都应该基于自身的参数上下文独立计算,不会共享或累积之前的状态。你当前的问题是因为闭包捕获了同一个acc变量,所有后续调用都修改这个共享变量,属于实现缺陷,不是柯里化的常规行为。
如何修改使其行为更符合直觉?
核心思路是:让每次返回的函数都持有独立的累加状态,而不是共享同一个变量。可以通过让辅助函数每次接收当前累加值,并返回携带新状态的新闭包来实现。
修改后的代码
function infiniteCurry(fn, startValue) { // helper接收当前累加值,返回新的函数 function helper(currentAcc) { return function(n) { if (n !== undefined) { // 计算新的累加值,返回持有该值的新helper闭包 return helper(fn(currentAcc, n)); } else { return currentAcc; } }; } // 初始调用传入startValue,返回第一个函数 return helper(startValue); } // 测试验证 function sum(a, b) { return a + b; } const curriedSum = infiniteCurry(sum, 0); console.log(curriedSum(1)(2)(3)() === 6); // true const add1 = curriedSum(1); console.log(add1(4)() === 5); // true console.log(add1(4)() === 5); // true,符合预期
实现原理
- 原实现中,
acc定义在最外层函数,所有helper调用共享同一个变量,导致状态累积。 - 修改后,
helper每次接收当前的累加值currentAcc,当传入新参数时,会计算出新的累加值,并返回一个新的helper闭包,这个新闭包持有更新后的currentAcc。这样每个中途生成的函数(比如add1),每次调用都会基于自己的初始状态重新计算,不会和其他调用共享状态。
简化版(箭头函数)
如果喜欢更简洁的写法,也可以用箭头函数实现:
const infiniteCurry = (fn, startValue) => { const helper = currentAcc => n => n !== undefined ? helper(fn(currentAcc, n)) : currentAcc; return helper(startValue); };
内容的提问来源于stack exchange,提问作者baNaNa
相关产品推荐
相关产品推荐

