谈到这个就有点头大。。
其实我还是蛮惧怕柯里化的,感觉就像大山一样,不过总要跨过去的是吧(╥╯^╰╥)
柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
说得简单点:
只传递函数一部分的参数来调用他,并且返回一个函数去处理剩下的参数,也叫作部分求值
还是举一个老掉牙的栗子
1 | function add(a, b, c) { |
那么这个时候add的柯里化_add可以为:1
2
3
4
5
6
7function _add(a) {
return function(b) {
return function(c) {
return a + b + c;
}
}
}
因此以下两个运算都是等价的:1
2
3add(1, 2, 3)
_add(1)(2)(3)
简单来说,柯里化其实就是一个参数收集的过程,将每一次传入的参数收集起来,然后在最里层再进行处理。
接下来自己手动实现一个简单的柯里化累加。
1 | const curring = function () { |
完工!⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄
这篇blog算是很简单的,不能够特别明显的凸显柯里化的优势,主要目的还是初识一下柯里化本身。
当然,柯里化通用式具备更加强大的能力,我们靠眼力自己封装的柯里化函数则自由度偏低,柯里化函数的运行过程其实是一个参数的收集过程,我们将每一次传入的参数收集起来,并在最里层里面处理。所以借助这个方式可以总结出一份柯里化的通用式。
这里借用梧桐大大的currying通用式:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34// 简单实现,参数只能从右到左传递
function createCurry(func, args) {
var arity = func.length; //函数的length表示形参个数
var args = args || [];
return function() {
var _args = [].slice.call(arguments);
[].push.apply(_args, args);
// 如果参数个数小于最初的func.length,则递归调用,继续收集参数
if (_args.length < arity) {
return createCurry.call(this, func, _args);
}
// 参数收集完毕,则执行func
return func.apply(this, _args);
}
}
function check(targetString, reg) {
return reg.test(targetString);
}
var _check = createCurry(check);
var checkPhone = _check(/^1[34578]\d{9}$/);
var checkEmail = _check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);
checkPhone('183888888');
checkEmail('xxxxx@test.com');