前言:最近面试连着两次被问到柯里化相关问题,于是又重新翻了一遍红宝书和文档,在此记录一些学习成果。
1.按照红宝书的定义,柯里化的基本方法和函数绑定是一样的:使用一个闭包返回一个函数。两者的区别在于,在函数被调用时,返回的函数还需要设置一些传入的参数。
2.针对实现add(1)(2)(3)(4)(5)这个问题,目前主要找到了两种解决方法。
方法1.明确参数个数的情况
function add() {
let args = Array.prototype.slice.call(arguments)
// console.log('add', args);
if (args.length === 5) {
return args.reduce((prev, item) => {
return prev + item
}, 0)
} else {
return function sum() {
let arg = Array.prototype.slice.call(arguments)
args = args.concat(arg)
if (!args.length) {
return args.reduce((prev, item) => {
return prev + item
}, 0)
} else {
return sum
}
}
}
}
方法2:不确定参数个数的情况,通过传空值告诉代码参数读取完毕
// 先定义求和方法
function add(...args) {
return args.reduce((a, b) => a + b)
}
// 再定义执行函数柯里化的方法
function currying(fn) {
let args = []
return function sum(...newArgs) {
if (newArgs.length) {
args.push(...newArgs)
return sum
} else {
// console.log('args', args);
const val = fn.apply(this, args)
args = []
return val
}
}
}
// 对add方法进行柯里化处理
const curriedAdd = curry(add)
console.log(addCurry(1)(2)(3)(4)(5, 6)()); // 21
3.还有一种方法是通过改写函数的toString()方法使函数返回计算结果,但是这种方法在我的实操中在chrome浏览器和vscode中均未正确执行,所以谨慎使用。
const curry_add = (...a) => {
let num = a.reduce((t, c) => t + c, 0)
const item = (...b) => {
num = num + b.reduce((t, c) => t + c, 0)
return item
}
item.toString = () => num
return item
}
console.log(curry_add(1)(2)(3)(4)(5));
// chrome中仍然返回函数
// (...b)=>{
// num = num + b.reduce((t,c)=>t+c,0)
// return itemFn
// }
4.目前我找到的两种方法都有缺陷,一种必须明确参数个数,另一种需要通过传空值来确认参数读取完毕,想知道有没有两全其美的办法,希望有大佬可以在评论区指点一下,十分感谢!