位置:首页 > 软件操作教程 > 编程开发 > JavaScript > 问题详情

JavaScript 函数柯里化

提问人:刘团圆发布时间:2020-11-25

■设计思路

    函数合成是把多个单一参数函数合成一个多参数函数的运算。例如,a(x)和b(x)组合为a(b(x)),则合成为f(a,b,X)。注意,这里的a⑻和b(x)都只能接受一个参数。如果接受多个参数,如a(x,y)和b(a,b,c),那么函数合成就会比较麻烦。

    这时就要用到函数柯里化。所谓柯里化,就是把一个多参数的函数,转化为单一参数函数。有了柯里化运算之后,我们就能做到所有函数只接受一个参数。

【实现方法】

    先用传递给函数一部分参数来调用它,让它返回一个函数,然后再去处理剩下的参数。也就是说,把多参数的函数分解为多步操作的函数,以实现每次调用函数时,仅需要传递更少或单个参数。例如,下面是一个简单的求和函数add()。

    var add = function (x, y) {

        return x + y;

    }

每次调用add(),需要同时传入两个参数,如果希望每次仅需传入一个参数,可以这样进行柯里化。

    var add = function (x) {         //柯里化

        return function (y) {

            return x + y

        }

    }

    console.log(add(2)(6));          //8,连续调用

    var addl = add(200);

    console.log(addl(2));            //202,分步调用

    函数add()接受一个参数,并返回一个函数,这个返回的函数可以再接受一个参数,并返回两个参数之和。从某种意义上讲,这是一种对参数的“缓存”,是一种非常高效的函数式运算方法。柯里化在DOM的回调中非常有用。

■实例设计

    设想curry可以接受一个函数,即原始函数,返回的也是一个函数,即柯里化函数。这个返回的柯里化函数在执行的过程中,会不断地返回一个存储了传入参数的函数,直到触发了原始函数执行的条件。例如,设计一个add()函数,计算两个参数之和。

    var add = function (x, y) {

        return x + y;

    }

    柯里化函数:

    var curryAdd = curry(add)

    这个add需要两个参数,但是执行curryAdd时,可以传入更少的参数,当传入的参数少于add需要的参数时,add函数并不会执行,curryAdd就会将这个参数记录下来,并且返回另外一个函数,这个函数可以继续执行传入参数。如果传入参数的总数等于add需要参数的总数,就执行原始参数,返回想要的结果。如果没有参数限制,最后根据空的小括号作为执行原始参数的条件,则返回运算结果。

【实现代码】

//柯里化函数 

function curry(fn) {

    var _argLen = fn. length;                   //记录原始函数的形参个数

    var _args = [].slice.call (arguments, 1); //把传入的第2个及以后参数转换为数组

    function wrap () {                         //内部函数

        //把当前参数转换为数组,与前面参数进行合并 

        _args = _args.concat([].slice.call(arguments)); 

        function act() {                //参数处理函数

            //把当前参数转换为数组,与前面参数进行合并 

            —args = _args.concat([].slice.call(arguments));

            //如果传;C参数总和大于等于原始参数的个数,触发执行条件 

            if ( ( _argLen == 0 && arguments.length == 0) ||

                    (_argLen > 0 && _args.length >= _argLen) ) {

                    //执行原始函数,并把^次传入参数传入进€,返回执行结果,停止curry return fn•apply(null, _args);

            }

            return arguments.callee;

    }

    //如果传入参数大于等于原始函数的参数个数,即触发了执行条件 

    if ( (_argLen == 0 && arguments.length ==0 ) ||

           (_argLen > 0 && _args.length >= —argLen) ) {

           //执行原始函数,并把^次传入参数传入进去,返回执行结果,停止curry return fn.apply(null, _args);

    }

    act.toString = function () {//定义处理函数的字符串表示为原始函数的字符串表示 return fn.toString ();

    }

    return act;             //返回处理函数

    }

    return wrap;            //返回 curry 函数

【应用代码】

    应用函数无形参限制。

设计求和函数,没有形参限制,柯里化函数将根据空小括号作为最后调用原始函数的条件。

//求和函数,参数不限

var add= function () {//把参数转换为数组,然后调用数组的reduce方法

    //迭代所有参数值,返回最后汇总的值

    return [].slice.call(arguments).reduce(function (a, b) {

        //如果元素的值为数值,则参与求和运算,否则设置为0,跳过非数字的值

        return (typeof a == "number" ? a : 0) + (typeof b == "mumber" ? b : 0);

    })

}

//柯里化函数

var curried = curry(add);

console.log(curried(1)(2)(3)());           //6

var curried = curry(add);

console.log(curried(1, 2, 3)(4)());        //10

var curried = curry(add,1);

console.log(curried(1, 2)(3)(3)());        //10

var curried = curry(add,1,5);

console.log(curried(1, 2, 3, 4)(5)());     //21


应用函数有形参限制。

设计求和函数,返回3个参数之和。

var add = function (a,b,c) {            //求和函数,3个参数之和

    return a + b+c;

}

//柯里化函数

var curried = curry(add,2)

console.log(curried(1)(2));            //5

var curried = curry(add,2,1)

console.log(curried(2));               //5

var curried = curry(add)

console.log(curried(1)(2)(6));         //9

var curried = curry(add)

console.log(curried(1, 2, 6));         //9

继续查找其他问题的答案?

相关视频回答
回复(0)
返回顶部