函数柯里化是指把多个参数的函数变换成接受一个单一参数的函数,一般通过闭包实现。
function myCurry(fn, ...args) {
// fn的参数个数
let length = fn.length;
// 真正要传入参数并执行的函数
return function () {
// 拼接旧数组和新传入参数 比如test(2,3)(4) 就是拼接[2,3]和[4]
let newArgs = [...args , ...arguments];
// 如果拼接后数组长度还未达到fn参数个数 说明参数还没传完 递归
if (newArgs.length < length) {
return myCurry.call(this, fn, ...newArgs);
// 参数传完了 调用函数
} else {
return fn.apply(this, newArgs);
}
}
}
function fn(a,b,c){
console.log(a*b*c);
}
let test = myCurry(fn);
//传2,3时输出ok 最后输出24
test(2)(3)(4);
//传(2,3)时输出ok 最后输出24
test(2,3)(4);
//newArgs长度一次满足 不输出ok 直接输出24
test(2,3,4);
上面这种手写可以应对大部分情况,除非fn的参数是不定长数组,此时length为0:
let fn = (...arr) => {};
console.log(fn.length) // 0
会使得上面手写中的传参数量判断不准确,因此下面这种写法可能更能涵盖所有情况,缺点在于必须在最后加上一个空括号代表传参结束,比较好理解就不加注释了:
// 手写函数柯里化
const curring = function (fn) {
const args = [];
return function result(...rest) {
if (rest.length === 0) {
return fn(...args)
} else {
args.push(...rest);
return result;
}
}
}
const sum = (...arg) => {
return arg.reduce((pre, cur) => {
return pre + cur
}, 0)
}
console.log(curring(sum)(1)(2, 5)(3)())