首先看看函数珂理化到底是什么?
根据维基百科上说的 柯里化,英语:Currying(果然是满满的英译中的既视感),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
看完上面的解释是不是有点迷茫,官方的解释的确有点官方,不是很容易理解。老规矩,我们还是通过一段代码进入珂理化的讲解。
// 普通的两数相加的函数
function add(a, b) {
return a + b;
}
// 珂理化后
function curryingAdd(a) {
return function(b) {
return a + b;
}
}
const res1 = add(10, 20);
const res2 = curryingAdd(10)(20);
console.log(res1); // 30
console.log(res2); // 30
从上面的代码可以看出,add函数珂理化后,两个参数变成了一个参数,最终返回了一个新的方法。这就是珂理化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
知道了函数珂理化到底是什么东西,下面我们一起来看看这个东西到底有什么好处?
1、参数复用
// 普通的正则验证字符串
reg.test(str);
// 封装成普通函数后
function check(reg, str) {
return reg.test(str);
}
check(/\d+/g, 'test') //false
check(/[a-z]+/g, 'test') //true
// 珂理化之后
function curryingCheck(reg) {
return function(str) {
return reg.test(str);
}
}
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)
hasNumber('test1') // true
hasNumber('testtest') // false
hasLetter('21212') // false
上面的例子是一个简单的正则校验,正常来说直接调用check函数就可以了,但是如果我有很多地方都要校验是否有数字,其实就是需要将第一个参数reg进行复用,这样别的地方就能够直接调用hasNumber,hasLetter等函数,让参数能够复用,调用起来也更方便。:转载至 flowsands。
2、延迟计算
function currying(fun) {
const args = [];
return function result(...arguments) {
if (arguments.length === 0) {
return fun(...args);
}
args.push(...arguments);
return result;
}
}
const add = (...args) => args.reduce((a, b) => a + b);
const sum = currying(add);
sum(1,2)(3);
sum(4);
sum(); // 10
这边首先是初步封装,通过闭包把初步参数给保存下来,然后通过获取剩下的arguments进行拼接,最后执行需要currying的函数。
3、动态创建函数
例如兼容现代浏览器和IE浏览器的添加事件方法,我们通常会这样写:
const addEvent = function(element, event, handle) {
if (window.addEventListener) {
if (element && event && handler) {
element.addEventListener(event, handler, false);
} else {
if (element && event && handler) {
element.attachEvent('on' + event, handler);
}
}
}
}
这种方法显然有个问题,就是每次添加事件处理都要执行一遍if {...} else if {...}。其实用下面的方法只需判断一次即可:
const addEvent = (function() {
if (window.addEventListener) {
return (element, event, handle) => {
element.addEventListener(event, handler, false);
}
} else {
return (element, event, handle) => {
element.attachEvent('on' + event, handler);
}
}
})();
这个例子,第一次if {...} else if {...}判断之后,完成了部分计算,动态创建新的函数来处理后面传入的参数,以后就不必重新进行计算了。这是一个典型的柯里化的应用。