前端进阶——函数柯里化

什么是柯里化?

柯里化指将一个接收多个参数的函数转化为接收一系列单个参数的函数,当传入单个参数的时候,不会立即求值,而是会将参数传入下一个内部函数(形成了闭包)直到真正需要求值时一次性进行求值。

柯里化的优缺点

优点:

1,提高函数的复用性

2,延迟执行:前面讲过传入参数时不会立即执行会传入下一个内部函数

3,部分参数应用

缺点:

1,难以理解与维护

2,性能影响:柯里化会生成多个闭包

柯里化例子

一,最基础的柯里化

//没有柯里化之前的函数
function add(x,y,z)
{return x+y+z}
//柯里化以后的函数
function add1(x){
    return (y)=>{
            return (z)=>{
                return x+y+z;            
            }
    }
}
//调用区别
add(1,2,3);//普通函数的调用
add1(1)(2)(3);//柯里化函数的调用
add1(1)(2)//会返回一个函数因为你还没传入第三个参数

二,常用柯里化(短信验证码前缀)

在用户使用短信验证登录的时候,我们获取手机号后需要添加前缀表明国家后再发送给相应的短信api(例如中国的前缀为+86,泰国为+66)那么为了方便我们可以先封装出一个表示各国手机号前缀的函数,这样面对手机号直接调用不同的前缀函数即可。

function add(str){
    return (number)=>{
        return str + number;   
    }
}
var addChina=add("+86");//国内手机号前缀
var addThailand=add("+66");//泰国手机号前缀
console.log(addChina("13418666666"));//+8613418666666

三,面试常考柯里化(实现一个可以相加任意长度数字的柯里化函数)

面试中经常要求你完成如下的一个功能函数:

add(1)(2)(3)(4)//输出10

add(1,2,3,4)//输出10

add(1)(2)(3,4)//输出10

add(1)(1)(1)(1)(1)(1)(1,1,1)(1)//输出10

看起来就十分让人头疼,但是我们一步一步慢慢来其实也是可以解决的

首先,这里无非就是想要实现两个功能:

1,实现这样一个函数:add(1,2,3...)可以正确输出里面所有参数的和(参数个数未知)

2,实现这样一个函数:add(1)(2)...可以正确输出所有项之和(项个数未知)

我们逐个进行破解

1,实现add(1,2,3...)

首先对于多个参数肯定是使用数组进行接收,然后在函数内进行数组的求和

这里有一个知识点,在js中如果我们函数的参数未知个数,就使用...arr的方法将传入参数装入arr中,这样arr中的每个参数就是传入的值

//解决向一个括号传入未知参数
function add(...arr){//利用...传入多个参数
   var num =  arr.reduce(function (prev, cur) {//利用数组reduce相加
      return prev + cur;
  }, 0);
  return num;
}
console.log(add(1,2,3,4,5,6));//输出21

这样我们就完成了多个参数相加,so easy!

2,实现add(1)(2)...

这个稍微要比上面的难一点,而且其实我也并没有完全实现面试问题上的功能(高情商:降低代码难度,使代码更加可读和易于维护)我是在最后自己添加了一个.end()方法来输出前面项的和。不管这些,我们来讨论一下如何实现,这里其实我第一时间就想到了递归,思路是先接收传入的一个参数将其定义为sum,然后return进入下一个函数,下一个函数中我们接收一个参数,再将参数与sum相加然后再return自身这个函数相当于进入下一层,然后再在函数体内定义一个关于我们一直递归的那个函数的方法(函数也是一个对象,也可以有属性与方法)end方法,用于输出。

function add1(num){
    var sum = num;//将获取到的参数赋值到sum
    var add2= (num2)={
        sum +=num2
        return add2;//定义一个链式函数不断调用自身    
    }
    var add2.end = ()=>{//设置add2的.end方法输出相加值
        console.log(sum);    
    }
    return add2;//进入add2函数
}
add1(3)(4)(90)(60).end();//输出157

 注意,最后两个并不是同时执行的,js在执行end方法前会先检查上一个方法是否为add2的方法再执行

3,整合

假设你看懂了上面两步,那么整合对于你来说就是绰绰有余

function add1(...num1){
  var first =  num1.reduce(function (prev, cur) {
    return prev + cur;
}, 0);
  var sum = first;
  var add2 = (...arr) =>{
    var num =  arr.reduce(function (prev, cur) {
      return prev + cur;
  }, 0);
    sum = sum + num ;
    return add2;
  }
  add2.end = function(){
    console.log(sum);
  }
  return add2;
}
add1(1,10,20)(2,10)(3)(4)(90)(60).end();

总结

柯里化在实际开发中也许用处没有那么大,但是我相信当你理解这种思维并且掌握了这门技术,你对js的理解一定会更上一层楼,很多的东西看起来十分的高大上难以理解,但是当你循序渐进,抽丝剥茧,你会发现也不过是很多的基础知识组成的罢了。