柯里化
柯里化指这样的一种函数,把接收多个参数的函数变换成接收一个单一参数的函数(单一参数为多个参数中的第一个)。避免了重复的去执行程序,等真正需要结果的时候再执行
举个例子
var sum= (a,b,c) => a+b+c
var foo = curry(sum)
通过柯里化处理,可以这样传递参数
foo(1)(2)(3)
foo(1)(2,3)
foo(1,2)(3)
curry的实现
通过Function.length获取原函数的形参个数,
通过闭包保存剩余参数,返回一个新的函数,拼接闭包中的参数和新函数的参数,对比原函数的形参个数,参数不足递归继续生成另一个新函数来收集参数,参数达标则调用原函数并传入所有参数。
function curry(fn) {
var fnLength = fn.length; // 获取原函数参数个数
if(fnLength<=1)
return fn; // 原函数无入参,直接返回原函数
var args = Array.prototype.slice.call(arguments, 1);
return function() {
var _args = Array.prototype.slice.call(arguments);
_args = args.concat(_args)
// 参数个数不够则递归
if (_args.length < fnLength) {
return curry(fn, ..._args);
}
// 参数满足个数
return fn(..._args);
}
}
输出结果:
var sum = (a,b,c) => a+b+c
var count = curry(sum)
var res1 = count(1)(2,3)
console.log(res1) // 6
var res2 = count(2)(3)(4)
console.log(res2) // 9
这只是简单的实现和应用柯里化,但是为什么要这样吧穿的参数分开呢?
柯里化的使用场景
- 参数复用
实现参数复用是柯里化的主要用途之一
例如正则验证:
//验证手机号码
function checkPhone(phone) {
return /^1[34578]\d{9}$/.test(phone);
}
//验证邮箱
function checkEmail(email) {
return /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(email);
}
验证手机号,验证邮箱我们就会写以上的函数用来验证,那如果验证身份证,学号,车牌号等等一些,那我们就要写很多这样的函数来验证,而且他们的不同就在于他们的正则表达式不同。
按照常规的写法,我们每验证一次,就要传一次正则。
function checkThis(reg,val) {
return reg.test(val)
}
checkThis(/^1[34578]\d{9}$/,'13822448822')
checkThis(/^1[34578]\d{9}$/,'13987532486')
checkThis(/^1[34578]\d{9}$/,'13112546398')
如果使用柯里化就可以这样写
function checkThis(reg) {
return function(val){
return reg.test(val)
}
}
var phoneCheck = checkThis(/^1[34578]\d{9}$/);
console.log(phoneCheck('13822448822'))
console.log(phoneCheck('13987532486'))
var emailCheck = checkThis(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/);
emailCheck('ab@fe.123.cn')
这样写就不需要每次都去传递正则表达式, 复用性强。