柯里化正则表达式
以前讲了函数的前置知识 函数式编程(一)—— 前置知识还有纯函数的知识 函数式编程(二)—— 纯函数编程
下面咱们能够进行函数式编程的基础内容 —— 柯里化。segmentfault
解决硬编码的问题数组
// 下面这段代码是解决了不纯的函数的问题,可是里面出现了硬编码 function checkAge (age) { let mini = 18 return age >= mini } // 普通的纯函数 function checkAge (min, age) { return age >= min } console.log(checkAge(18, 20)) //true console.log(checkAge(18, 24)) //true console.log(checkAge(20, 24)) //true // 常常使用18,这段代码是重复的。避免重复 function checkAge (min) { return function (age) { return age >= min } } let checkAge18 = checkAge(18) let checkAge20 = checkAge(20) console.log(checkAge18(20)) //true console.log(checkAge18(24)) //true
柯里化:当函数有多个参数的时候,咱们能够对函数进行改造。咱们能够调用一个函数,只传递部分的参数(这部分参数之后永远不变),而后让这个函数返回一个新的函数。新的函数传递剩余的参数,而且返回相应的结果。缓存
// ES6 let checkAge = min => (age => age >= min) // 输出相同
_.curry(func)闭包
const _ = require('lodash') // 参数是一个的为一元函数,两个的是二元函数 // 柯里化能够把一个多元函数转化成一元函数 function getSum (a, b, c) { return a + b + c } // 定义一个柯里化函数 const curried = _.curry(getSum) // 若是输入了所有的参数,则当即返回结果 console.log(curried(1, 2, 3)) // 6 //若是传入了部分的参数,此时它会返回当前函数,而且等待接收getSum中的剩余参数 console.log(curried(1)(2, 3)) // 6 console.log(curried(1, 2)(3)) // 6
判断字符串中有没有空白字符,或者提取字符串中全部空白字符,可使用字符串的match方法:''.match(/\s+/g)
函数式编程
可是咱们要是写一个数组的去处空白字符的方法,上面的代码就没法重用。那咱们如何用函数式方法去写函数
function match(reg, str) { return str.match(reg) }
reg的表达式是重复的,上面的函数如何柯里化,思路是这样的:ui
//柯里化处理 const _ = require('lodash') //利用lodash的curry函数,第一个参数是匹配规则,第二个参数是字符串,生成一个match函数 const match = _.curry(function (reg, str) { return str.match(reg) }) // 根据规则haveSpace是一个匹配空格的函数 const haveSpace = match(/\s+/g) console.log(haveSpace("hello world")) //[ ' ' ] console.log(haveSpace("helloworld")) //null // 由此能够判断字符串里面有没有空格 // 那若是是数字的话怎么办呢? // 根据规则haveNumber是一个匹配数字的函数 const haveNumber = match(/\d+/g) console.log(haveNumber('abc')) // null // 对于数组怎么匹配元素中有没有空格 const filter = _.curry(function(func, array) { return array.filter(func) }) // filter函数,第一个参数传递匹配元素中有没有空格 //第二个参数是指定的数组 console.log(filter(haveSpace, ['John Connor','John_Donne'])) // [ 'John Connor' ] // 若是上述写仍是比较麻烦,那么能够再封装一个函数出来 // filter能够传一个参数,而后返回一个函数 // 这个findSpace就是匹配数组元素中有没有空格的函数 const findSpace = filter(haveSpace) console.log(findSpace(['John Connor','John_Donne'])) // [ 'John Connor' ]
下面对上面的思路作一个小的总结,柯里化的好处就是咱们能够最大程度的重用咱们的函数。编码
const _ = require('lodash') //match函数是根据一些正则,匹配字符串,返回匹配结果 const match = _.curry(function (reg, str) { return str.match(reg) }) //haveSpace函数是一个匹配空格的函数 const haveSpace = match(/\s+/g) //haveNumber函数是一个匹配数字的函数 const haveNumber = match(/\d+/g) //filter函数是定义一个数组和过滤规则,返回符合匹配规则的数组 const filter = _.curry(function(func, array) { return array.filter(func) }) //findSpace函数是匹配数组元素中有空格并返回符合状况的数组的函数 const findSpace = filter(haveSpace)
咱们找一个以前作过的例子分析一下
const _ = require('lodash') function getSum (a, b, c) { return a + b + c } const curried = _.curry(getSum) console.log(curried(1, 2, 3)) // 6 console.log(curried(1)(2, 3)) // 6 console.log(curried(1, 2)(3)) // 6
实现一个柯里化转换函数要进行分析
// 模拟柯里化函数 function curry (func) { // 取名字是为了下面实参小于形参的时候用的 return function curriedFn(...args) { // 判断实参和形参的个数 if(args.length < func.length) { return function() { // 等待传递的剩余参数,若是剩余函数的参数加上以前的参数等于形参,那么就返回func // 第一部分参数在args里面,第二部分参数在arguments里面,要将两个合并而且展开传递(使用...) // concat函数要合并两个数组,arguments为伪数组,因此用Array.from进行转换 return curriedFn(...args.concat(Array.from(arguments))) } } // 若是实参大于等于形参的个数 // args是剩余参数,是个数组形式,而返回的时候要展开(使用...) return func(...args) } } // test const curriedTest = curry(getSum) console.log(curriedTest(1, 2, 3)) // 6 console.log(curriedTest(1)(2, 3)) // 6 console.log(curriedTest(1, 2)(3)) // 6