函数柯里化

Posted scdisplay

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数柯里化相关的知识,希望对你有一定的参考价值。

1.什么是柯里化

柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。(百度百科搜一下就有)。

从一个普通函数得到一个柯里化函数的过程叫做函数的柯里化,返回的函数称为经过柯里化的函数

函数柯里化的技术来自于一种编程思想,就是一个复杂的问题可以通过分步的方式来求解,分步可以保证代码逻辑的清晰易懂。

2.举个例子

function add_1(a,b,c){//普通函数
    return a+b+c
}
console.log(add_1(1,2,3))

function add_2(a,b){//柯里化函数
    return function(c){
        return a+b+c
    }
}
console.log(add_2(1,2)(3))

function add_3(a){//柯里化函数
    return function(b){
        return function(c){
            return a+b+c
        }
    }
}
console.log(add_3(1)(2)(3))

function curry(func){//函数的柯里化过程
    return function(a,b){
        return function(c){
            return func(a,b,c)
        }
    }
}

function curry2(func){//函数的柯里化过程
    return function(a){
        return function(b){
            return function(c){
                return func(a,b,c)
            }
        }
    }
}

var add_2=curry(add_1)
var add_3=curry2(add_1)

  我们可以通过分步的return来实现参数的分步传递,将add_1这个普通函数变为add_2或者add_3的过程称为函数的柯里化。可以预见随着传参的不断增加,柯里化过程就要不断的增加,是否可以从curry1,curry2这两个柯里化过程中得出一个通用的函数呢?这就是柯里化函数的通用式。

柯里化函数的运行过程其实是一个参数的收集过程,我们将每一次传入的参数收集起来,最后传给函数执行。
function add_n(func,args){//func是表示处理函数;args表示所有参数
    let length=func.length;//函数的形参个数,决定了要柯里化的次数
    var args=args || [];//柯里化时依次收集的参数存储变量,包含了所有已收集的传参

    return function(){
        let _args=Array.from(arguments);//收集柯里化时函数参数
        [].push.apply(_args,args);//将本轮柯里化运行时的参数添加到已收集的参数数组

        if(_args.length<length){//如果参数未收集完,即已收集的参数个数小于函数的形参个数时,递归调用
            return add_n.call(this,func,_args);
        }

        //当全部参数收集完成时,将所有参数传入函数中执行
        return func.apply(this,_args)
    }
}


var test=function(a,b,c){
    return a+b+c
}

var test_curry1=add_n(test)
var test_curry2=add_n(test,[1])
test_curry1(1)(2)(3) //6
test_curry2(2)(3)   //6

  

3.实际的应用场景

理解了柯里化的过程,就要注意柯里化的思想更为重要,可以用来拆分逻辑。一个关于校验的例子:

function check(partner,str){
    return partner.test(str)
}

function check_curry(partner){
    return function(str){
        return partner.test(str)
    }
}

var check_phone=check_curry(/^1[34578]d{9}$/)
var check_email=check_curry(/^(w)+(.w+)*@(w)+((.w+)+)$/)

//使用时较为复杂难用
check(/^1[34578]d{9}$/,‘18057192235‘)
check(/^(w)+(.w+)*@(w)+((.w+)+)$/,‘[email protected]‘)

//使用时更为清晰明了
check_phone(‘18057192235‘)
check_email(‘[email protected]‘)

  在柯里化的实现中,我们知道柯里化虽然具有了更多的自由度,但同时柯里化通用式里调用了arguments对象,使用了递归与闭包,因此柯里化的自由度是以牺牲了一定的性能为代价换来的。只有在情况变得复杂时,才是柯里化大显身手的时候。

参考文章:https://www.jianshu.com/p/5e1899fe7d6b

  

 

以上是关于函数柯里化的主要内容,如果未能解决你的问题,请参考以下文章

手写柯里化,实现柯里化

js高阶函数应用—函数柯里化和反柯里化

柯里化函数快速排序外边距重叠

函数式编程:纯函数&柯里化&组合函数

函数柯里化

JS中的柯里化及精巧的自动柯里化实现