注册

一文让你彻底悟透柯里化

什么是柯里化?



在数学和计算机科学中,柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术



前端为什么需要使用柯里化?



前端使用柯里化的用途主要就是简化代码结构,提高系统的维护性,一个方法只有一个参数,强制了功能的单一性,很自然就能做到功能内聚,降低耦合


一句话就是:降低代码重复率,提高代码适应性



普通函数



实现一个普通的累加函数,调用时需要传入三个参数,如果少 传则输出NaN,多传则后面的参数都无效



function add(a,b,c){
   return a + b + c
}
add(1,2,3) //6

普通柯里化函数



实现一个普通的柯里化函数(含有柯里化性质),通过调用传参的方式将函数传入,并传入参数进行运算,返回一个新的函数的参数进行累计(取决于传入函数时传入参数的个数以及执行函数的传入参数进行累计)



function add(a, b, c) {
 return a + b + c;
}

function fixedCurryAdd(fn) {
 const arg = [].slice.call(arguments, 1);
 return function () {
   const newArg = arg.concat([].slice.call(arguments, 0));
   return fn.apply(this, newArg);
};
}
const curryAdd = new fixedCurryAdd(add, 1);
console.log(curryAdd(2,11)); //14


柯里化函数



通过上面的含有柯里化性质的函数可以看出 ,要实现柯里化函数可以有多种传参方式,例如:


newAdd(1,2,3,4)
newAdd(1)(2,3,4)
newAdd(1)(2,3)(4)
newAdd(1)(2)(3)(4)

含有多种传参方式 ,无论哪种方式,最后都会把所需参数传入,但是柯里化函数只是期望你执行这次函数传入所需参数个数,并不强求你传入所需参数(4个,可传1个后续补上即可,最后一次凑齐4个即可)



function add(a, b, c) {
 return a + b + c;
}
function CurryAdd(fn){
   let arg = [].slice.call(arguments,1);
   return function(){
       let newArg = arg.concat([].slice.call(arguments,0));
       return fn.apply(this,newArg);
  }
}
function Curry(fn,length){
   let len = length|| fn.length; //获取传入函数所需参数的个数
   return function(){
       if(arguments.length <len){
           const callback = [fn].concat([].slice.call(arguments,0));
           return Curry(CurryAdd.apply(this,callback),len-arguments.length);
      }else{
           return fn.apply(this,arguments);
      }
  }
}
let adds=new Curry(add)
let a = adds(1)(2)
console.log(a(1)); //4


以上完善柯里化函数的整个书写。下面来捋一下这个书写过程的思路



  • 首先柯里化函数期待传入一个函数,并且返回一个函数(add)
  • 通过fn.length获取当前以传入的参数个数
  • 在返回函数中判断当前参数是否已传入完毕

    • 如果已传入fn.length个 则直接调用传入函数
    • 如果未传入fn.length个 则通过callback将fn放到第一位在进行合并arguments作为下一次进入此函数的参数,通过CurryAdd 函数对参数再进行一遍"过滤",通过递归调用自己来判断参数是否已经达到fn.length个从而实现柯里化




柯里化应用



说了这么多,那么柯里化到底能做哪些应用呢?




在前端页面中,向后端进行数据请求时,大部分都用到ajax进行请求


function ajax(method,url,data){
...ajax请求体(不作书写)    
}
ajax("post","/api/getNameList",params)
ajax("post","/api/getAgeList",params)
ajax("post","/api/getSexList",params)

如果有这么多请求且每次都需要写请求方式("post"),页面多了请求多了自然成为冗余代码,那么优化一下


const newAjax = Curry(ajax);
const postAjax = newAjax("post")
...

如果url还有类似的那么就可以重复以上的代码,这样能减少相同代码重复出现



作者:Govi
来源:juejin.cn/post/7389049604632166427

0 个评论

要回复文章请先登录注册