一、介绍
柯里化(Currying)是一种将接受多个
参数的函数转换成一系列接受一个
参数的函数的技术。
在 JavaScript 中,可以使用柯里化来创建一个函数,使其可以接受部分参数,并返回一个新的函数来接受剩余的参数。
下面是一个简单的示例,演示如何使用柯里化来创建一个加法函数:
// 加法函数
const add = (x, y) => x + y;
// 柯里化函数
// const curriedAdd = x => y => x + y
const curriedAdd = x => {
return function(y) {
return x + y;
}
};
// 使用
console.log(add(2, 3)); // 输出 5
console.log(curriedAdd(2)(3)); // 输出 5
在这个示例中,curriedAdd
是一个柯里化函数。当我们调用 curriedAdd(2)
时,它返回一个新函数,这个新函数接受参数 y
,并将 x
(在这里是 2
)与 y
相加。所以 curriedAdd(2)(3)
实际上是将 2
和 3
相加。
柯里化可以使函数更加灵活,可以更方便地部分应用参数或者延迟执行。
二、Currying Transformation
示例一:
console.log(curry(sum)(1)(2)); // 3
// curry(f) does the currying transform
function curry(f) {
return function(a) {
return function(b) {
return f(a, b);
};
};
}
// usage
function sum(a, b) {
return a + b;
}
示例二:
console.log(currying(sum)(1)(2, 3)(4)); // 10
function currying(fn) {
return function(a) {
return function(b, c) {
return function(d) {
return fn(a, b, c, d);
}
}
}
}
function sum(a, b, c, d) {
return a + b + c + d;
}
示例三:
console.log(add(1)(2)(3)(4)(5).sum()); // 15
console.log(add(1)(2, 3)(4)(5).sum()); // 15
function add(...args) {
let total = args.reduce((acc, val) => acc + val, 0);
function innerAdd(...nextArgs) {
if (nextArgs.length === 0) {
return total;
}
total += nextArgs.reduce((acc, val) => acc + val, 0);
return innerAdd;
}
innerAdd.sum = function() {
return total;
};
return innerAdd;
}
三、优势
柯里化就是只传递给函数部分参数,而让其返回一个函数去处理剩余的参数,而费这么大力气如此封装,好处也是很明显的:
1. 参数复用
将变化的参数封装成一个单独的柯里化函数,其他地方复用:
// const check = (reg, text) => return reg.test(text);
const curringCheck = (reg) => {
return function(text) {
return reg.test(text);
}
}
let hasNumber = curringCheck(/\d+/g);
let hasletter = curringCheck(/[a-z]+/g);
当有许多地方需要校验是否有数字或是否有字母,就需要复用 reg
参数,利用柯里化将其封装,会让代码可读性更强。
2. 避免判断逻辑重复执行
const on = (ele, event, handler) => {
if(document.addEventListener) {
console.log("support addEventListener");
if(ele && event && handler) {
ele.addEventListener(event, handler, false);
}
} else {
console.log("not support addEventListener");
if(ele && event && handler) {
ele.attactEvent('on'+event, handler);
}
}
}
// 利用柯里化实现自执行并返回一个新函数,并提前确定执行哪个逻辑,避免每次都要进行判断
const on = (function() {
if(document.addEventListener) {
return function(ele, event, handler) {
if(ele && event && handler) {
ele.addEventListener(event, handler, false);
}
}
} else {
return function(ele, event, handler) {
if(ele && event && handler) {
ele.attactEvent('on' + event, handler);
}
}
}
})();
// 上述代码只需要执行一次
on(element, event, handler);
注意,上述代码最大价值就是逻辑复用,即判断逻辑只需要执行一次即可。