初始科里化
刚认识到科里化函数是从一道面试题开始:
add(1)(2)(3)(4) = 10;
- 疑问:没见到过这题的小伙伴肯定很懵逼, 怎么函数add(1)后面还能跟(2)(3)(4)
- 原理就是add(1)返回一个函数。因此可以拼接上(2),继续执行直达最后
- 如下图的函数结构所示
function add (a) {
return function (b) {
return function (c) {
return function (d) {
return a + b + c + d
}
}
}
}
- 对于程序猿来说这种方法肯定是不美丽的,那么就用科里化的函数类解决这个问题了
- 来看看科里化是怎么解决的吧
- 原理:利用闭包,将一个函数接受多个参数变成一步步接受单个或多个参数
function fn(a,b,c,d){
return [...arguments].reduce((a,b)=>a+b)
}
function currying(fn){
let len = fn.length;
let args = []
return function _c(){
args = [...args,...arguments];
if(args.length<len){
return _c
}else{
return fn.apply(this,args)
}
}
}
let add = currying(fn);
let res = add(1)(2)(3)(4);
- 那么第一种是定长的情况,那么不定长呢?
- 对于不定长,我们设定一个边界条件:即传入的参数第一次为空就代表参数接收完成
function fn2(){
return [...arguments].reduce((a,b)=>a+b)
}
function currying2(){
let args = [];
return function _c(){
args = [...args,...arguments];
if(arguments.length){
return _c
}else{
return fn.apply(this,args)
}
}
}
let add2 = currying2(fn2);
let res2 = add2(1)(2,3,9,9)()
科里化函数的应用
- 那么讲了原理,让我们来看看实际程序中这个函数的使用
参数复用/延迟运行
- 可以提前传入一个指定的参数,将返回函数(这个函数就可以复用)传入另外的参数,
- 同时这个函数也达到了了延迟运行的目的
- bind也用了currying函数的思想
function check(reg, txt) {
return reg.test(txt)
}
check(/\d+/g, 'test')
check(/[a-z]+/g, 'test')
function curryingCheck(reg) {
return function(txt) {
return reg.test(txt)
}
}
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)
hasNumber('test1')
hasNumber('testtest')
hasLetter('21212')
hasLetter('21212')