JavaScript高阶函数实现——柯里化(Currying)

@wanqiuz 2018-04-26 05:47:57发表于 wanqiuz/blog-articles JavaScriptcurrying高阶函数

1 柯里化

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

举个例子:
柯里化前:

function add(a, b) {
    return a + b;
} // 执行 add 函数,一次传入两个参数即可
add(10, 2) // 12

柯里化后:

var add = function(a) {
    return function(b) {
        return a + b;
     };
};
var addTen = add(10);
addTen(2); // 12

那么我们为什么要使用柯里化呢?

(1) 参数复用

(2) 延迟计算

(3) 提前返回

首先柯里化可以使得参数复用并且延迟计算,也就是说像上面的例子,比如我们的 a 值一直都是 10,只是 b 值在变化,那么这个时候用到柯里化,就可以减少一些重复性的传参。

比如 b 是 2,3,4

那么在柯里化前的调用就是:

add(10,2)
add(10,3)
add(10,4)

而在柯里化之后,就像上面的例子中写的,我们通过定义

var addTen = add(10);

将第一个参数 a 预置了 10,

之后我们只需要调用

addTen(2)
addTen(3)
addTen(4)

就可以了。

而在这个过程中,如果使用柯里化前的代码,或当即就把结果计算出来,而在柯里化之后,我们可以现传入一个 10,然后在想得到真正结果的时候再传入另一个参数,体现了延迟计算。

同时柯里化函数还可以 提前返回,很常见的一个例子,兼容现代浏览器以及IE浏览器的事件添加方法。我们正常情况不使用柯里化可能会这样写

var addEvent = function(el, type, fn, capture) {
    if (window.addEventListener) {
        el.addEventListener(type, function(e) {
            fn.call(el, e);
        }, capture);
    } else if (window.attachEvent) {
        el.attachEvent("on" + type, function(e) {
            fn.call(el, e);
        });
    } 
};

这个时候我们没调用一次 addEvent,就会进行一次 if else 的判断,而其实具体用哪个方法进行方法的绑定的判断执行一次就已经知道了,所以我们可以使用柯里化来解决这个问题:

var addEvent = (function(){
    if (window.addEventListener) {
        return function(el, sType, fn, capture) {
            el.addEventListener(sType, function(e) {
                fn.call(el, e);
            }, (capture));
        };
    } else if (window.attachEvent) {
        return function(el, sType, fn, capture) {
            el.attachEvent("on" + sType, function(e) {
                fn.call(el, e);
            });
       };
    }
})();

一开始的自执行函数,完成了对 addEvent 具体使用 哪个方法的判断,之后在调用传参的时候都是直接给了已经判断好的返回方法,所以使用了柯里化 减少了我们每次的判断,提前返回了我们需要的具体方法。

2 柯里化和箭头函数的结合

先来一个简单的例子,咱们就利用上面的 add 方法:

es5写法:

var add = function(a) {
    return function(b) {
        return a + b;
    };
};

而当你加上了箭头

let add = a => b => a + b

参考并感谢: