柯里化函数

98 阅读1分钟

柯理化定义

有人说这是工厂模式,因为这个确实是通过一个函数生成另一个可用的函数,有人说这是建造者模式,因为可以多层套用,建造出自己想要的函数实例。 举个例子

// 普通加法
function sum(a,b){
	return a+b
}
sum(1,2)
function ksum (a){
	return (b)=>{
    return a+b
  }
}
const sum1 = ksum(1)
sum1(2)

例子里,使用柯理化函数就能去掉一个固定的入参,当然,前提是固定的入参,但是这就有一个问题,如果是一层封装,这样写还简单,如果是多层就不好写了,冗余

function sum2(a){
  return (b)=>(c)=>(d)=>(e)=>a+b+c+d+e
}
sum2(1)(2)(3)(4)(5)

不美观了,所以需要一个函数来进行函数向柯理化的转换,这样就不用重复代码了,当然,从定义上看,这肯定是一个递归函数

function curry(fn, args) {
  var length = fn.length;
  var args = args || [];
  console.log('柯理化生成函数执行', args, fn.length);
  return function () {
    newArgs = args.concat(Array.prototype.slice.call(arguments));
    console.log('arguments', [...arguments], newArgs, args);
    if (newArgs.length < length) {
      // 这一步是保证参数全都柯理化完成
      return curry.call(this, fn, newArgs);
    } else {
      console.log('柯理化最后一步,执行');
      return fn.apply(this, newArgs);
    }
  };
}

//需要被柯里化的函数
function multiFn(a, b, c) {
  return a * b * c;
}

//multi是柯里化之后的函数
var multi = curry(multiFn);
console.log(multi(2)(3)(4));
console.log(multi(2, 3, 4, 5));
console.log(multi(2, 6)(3, 4, 5));
console.log(multi(2, 3)(4));

其实这段代码我觉得并没有什么用,柯理化的作用体现的不是很明显 ​

柯理化的应用场景

为了减少重复传递的不变参数,比如写一个手机号校验函数

function valiPhone(reg, phone){
	if(phone && reg.test(phone)){
    return Promise.resolve()
  }
  return Promise.reject('x')
}

这样子每次都需要传入reg(其实这个例子不太好) 所以我们可以柯理化(抽象出)函数,一个生成test工具

function curryTest(reg){
  return (str)=>{
    reg.test(str)
  }
}
const valiPhone = curryTest(/\d/)

这样也增加了可拓展性