函数柯里化
区分一下 高阶函数和函数柯里化的概念
高阶函数:1)函数可以作为参数 2)函数可以作为返回值
我们平时使用的setTimeout,map,filter,reduce等都属于高阶函数,当然还有我们今天要说的函数的柯里化,也是高阶函数的一种应用
柯里化:
它用于创建已经设置好了一个或多个参数的函数。函数的柯里化的基本使用方法和函数绑定是一样的:使用一个闭包返回一个函数。两者的区别在于,当函数被调用时,返回的函数还需要设置一些传入的参数,总之函数的柯里化就是将多参数函数转换成单参数函数,这里的单参数并不仅仅指的是一个参数
具体实现:
function currying(fn, length) {
length = length || fn.length; // 注释 1
return function (...args) { // 注释 2
return args.length >= length // 注释 3
? fn.apply(this, args) // 注释 4
: currying(fn.bind(this, ...args), length - args.length) // 注释 5
}
}
注释:
- 注释 1:第一次调用获取函数 fn 参数的长度,后续调用获取 fn 剩余参数的长度
- 注释 2:currying 包裹之后返回一个新函数,接收参数为 ...args
- 注释 3:新函数接收的参数长度是否大于等于 fn 剩余参数需要接收的长度
- 注释 4:满足要求,执行 fn 函数,传入新函数的参数
- 注释 5:不满足要求,递归 currying 函数,新的 fn 为 bind 返回的新函数(bind 绑定了 ...args 参数,未执行),新的 length 为 fn 剩余参数的长度
const currying = fn =>
judge = (...args) =>
args.length >= fn.length
? fn(...args)
: (...arg) => judge(...args, ...arg)
es5
function currying(fn) {
let args = [];
return function closureFn() {
args = args.concat(Array.from(arguments));
if (args.length < fn.length) return closureFn;
const res = fn.apply(this, args);
args = []; return res;
}
}
const sum = currying((a, b) => a + b);
console.log(sum(1, 2) === sum(1)(2));
参考:【github】