柯里化正則表達式
以前講了函數的前置知識 函數式編程(一)—— 前置知識還有純函數的知識 函數式編程(二)—— 純函數編程
下面咱們能夠進行函數式編程的基礎內容 —— 柯里化。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