函数的柯里化

概念

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

为什么要使用柯里化

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

调用形式
function add(a, b, c) {}

var newAdd = Curry(add);
newAdd(a)(b)(c);
newAdd(a)(b, c);
newAdd(a, b)(c);

即原始函数是 固定 参数个数的函数,柯里化后的函数可以分多次传参,直到凑齐原函数执行所需要的参数个数。

柯里化的应用
函数的柯里化_第1张图片
柯里化应用-ajax.png

如图,ajax函数被调用的次数非常频繁,且每次需要传固定个数的参数,那么可以利用柯里化,先传部分参数,将ajax函数导向不同分支,形成方便调用的其他函数。
分化流程如下:


函数的柯里化_第2张图片
柯里化-ajax流程.png

即可以分别先传GET、POST参数,分别形成两个新的函数,用于发送不同形式的请求;再传URL参数形成新函数,用于向固定地址发送请求,依次类推。。。


函数的柯里化_第3张图片
柯里化-ajax应用演示.png
柯里化的实现
/**
 * 固定参数个数的柯里化
 * @param {Function} fn 需要进行柯里化的函数
 */
function FixedParamsCurry(fn) {
    // 此函数的第一个参数是需要柯里化的函数fn,后面的参数是实际需要传入fn种进行执行的参数
    // 获取fn之后的所有参数,保存在_arg种
    var _arg = [].slice.call(arguments, 1);

    // 返回一个函数,这个函数继续等待后续参数传入,与前面的传参_arg合并,然后传给fn执行
    return function () {
        var newArg = _arg.concat([].slice.call(arguments, 0));
        return fn.apply(this, newArg);
    }
}

/**
 * 将一个固定参数个数的函数柯里化
 * @param {Function} fn 需要实际执行的函数fn
 * @param {*} length 函数fn执行实际需要的参数个数
 */
function Curry(fn, length) {
    // fn需要为固定参数个数的函数,length为明确指定参数个数
    // 以length记录fn的参数个数是几个
    // Function.length 表示函数的形参个数,若是形参有默认值,则不会计入参数个数
    var length = length || fn.length;

    // 返回一个函数,等待继续传入其他参数
    return function () {
        // 如果本次传入的参数个数,小于fn执行要求的参数个数,那么继续返回新函数等待传入参数
        if (arguments.length < length) {
            // 将新参数做成[fn, a, b, c...]的形式
            var combined = [fn].concat([].slice.call(arguments, 0));

            // 生成新函数,等待其他参数传入,那么剩余要传的参数个数应为fn实际执行需要的个数 length,减去本次已经传入的个数arguments.length
            return Curry(FixedParamsCurry.apply(this, combined), length - arguments.length);
        } else {
            // 若是本次参数个数就足够,那么执行fn,返回fn的结果
            return fn.apply(this, arguments);
        }
    }
}

// 测试
// add是一个固定参数个数的函数
function add(a, b, c, d) {
    return a + b + c + d;
}

var newAdd = Curry(add);
var num1 = newAdd(1)(2)(3)(4);
var num2 = newAdd(1, 2)(3, 4);
console.log(num1);
console.log(num2);

var newAdd1 = Curry(add);
var newAdd2 = newAdd1(2);
var num3 = newAdd2(3, 5, 5);
console.log(num3);

你可能感兴趣的:(函数的柯里化)