Skip to content

鼓励作者:欢迎打赏犒劳

柯里化

函数作为一等对象最大的好处就是可以在程序运行时创建它们并将之储存在变量里。如下

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

add(5, 2);
add(5, 2);
add(5, 100)

这里我们可以优化 add 函数,每次使用 add 函数都是将数字 5 和其他三个数字进行相加,如果能把数字 5 内置在函数中而不用调用时作出参数传进去是个不错的注意。我们可以用柯里化(partial application 或者 currying)

javascript
var add = function (a, b) {
    return a + b;
};
function add5(b) {
    return add(5, b);
}
add5(2);
add5(5);
add5(200);

现在,我们创建了一个调用 add 函数并预置了一个参数值(这里是 5)的 add5 函数, add5 函数本质上来讲其实就是预置了一个参数(柯里化)的 add 函数。不过,这个例子并没展示出这门技术动态的一面,如果我们提供的默认值是另外一个应该这么做?按照上面的例子,我们必须再次新建一个函数来提供一个新的预置参数。

javascript
function add(a, b) {
    return a + b;
}
function curryAdd(a) {
    return function (b) {
        return add(a, b);
    };
}
var add5 = curryAdd(5);

add5(2);
add5(5);
add5(200);

现在来介绍一下这个新的函数 curryAdd,它接收一个参数,这个参数会作为 add 函数的参数 a,同时返回一个新的匿名函数,这个匿名函数接收一个参数 b 来作为 add 函数的另一个参数。

当我们通过 curryAdd(5) 来调用这个函数时,它返回一个已经储存了我们一个明确参数值的函数,这个参数值此时被当做时这个匿名函数的一个局部变量。因为我们创建了一个闭包,所以即使这个匿名函数已经执行完毕,但我们还是可以通过它来最终求出我们需要的 a + b 的值

javascript
const init = (platform) => ({
    host: 'http://www.baidu.com',
    payload: null,
    isSpa: true
}) => {
    console.log('1111')
}

手写柯里化

柯里化就是一种将使用多个参数的一个函数转换为一系列使用一个参数的函数的技术

通俗来讲:用闭包把参数保存起来,当参数的数量足够执行函数了,就开始执行函数

实现

  • 判断当前函数传入的参数是否大于或等于 fn 需要参数的数量,如果是,直接执行 fn
  • 如果传入参数数量不够,返回一个闭包,暂存传入的参数,并重新返回 currying 函数
javascript
function currying(fn, ...args) {
    if (args.length >= fn.length) {
        return fn(...args);
    } else {
        return (...args2) => currying(fn, ...args, ...args2);
    }
}

我们来一个简单的实例验证一下:

javascript
function fun(a, b, c) {
    return a + b + c;
}
const curryingFun = currying(fun);
curryingFun(1)(2)(3); // 1 2 3
curryingFun(1, 2)(3); // 1 2 3
curryingFun(1, 2, 3); // 1 2 3

参考资料