柯理化是一種關於函數的高階技術。
柯里化是一種函數的轉換,它是指將一個函數從可調用的 f(a, b, c) 轉換爲可調用的 f(a)(b)(c)。
柯里化不會調用函數。它只是對函數進行轉換。
一個最簡單的例子javascript
// 本來的sum函數以及應用 function sum(a, b) { return a + b; } sum(1,2) // 3 // 柯理化後的sum函數以及應用 function curry_sum(a) { return function(b){ return a+b } } sum(1)(2) // 3 // 或者 fn=sum(1) fn(2) ==>3
柯理化的使用確定不是爲了裝逼,或者說不單單爲了裝逼。java
柯理化能夠延遲執行,達到參數複用的目的。(我的理解動態函數和惰性函數和柯理化沒啥關係)node
原先是sum(1,2)當即執行,如今能夠先fn=sum(1) 而後再fn(2) 這個就對於函數的執行可控了git
第一次傳參並不執行,咱們先埋伏它一波。github
後面函數執行的時候複用的咱們第一次傳的參,這個就叫延遲執行,參數複用。這樣能夠大幅度簡化咱們的代碼。ajax
雖然咱們能夠根據柯理化的思想,寫出咱們想要的函數,好比以前的curry_sum
segmentfault
可是咱們最好能寫個更通用的柯理化函數,它接受一個fn,返回一個包裝後的函數curry_fn,完成咱們所須要的參數複用和延遲執行功能。api
這裏參考Lodash咱們看一個curry函數長啥樣閉包
/** * 參數 * func: 用來柯里化(curry)的函數。 * [arity=func.length] : 須要提供給 func 的參數數量。 * * 返回 * (Function): 返回新的柯里化(curry)函數。 */ function curry(func, [arity=func.length]){ }
咱們給出它的測試用例app
// curry.test.js const{curry} = require('./index') test('curry',()=>{ const add = (a,b,c)=>{ return a+b+c } const sayhi = function(){ return this.name } const curry_add = curry(add) const curry_sayhi = curry(sayhi) const obj = {name:'fyy'} expect(curry_sayhi.call(obj)).toBe('fyy') expect(curry_add(2)(3)(4)).toBe(9) expect(curry_add(1)(2,3)).toBe(6) expect(curry_add(1,2)(2)).toBe(5) expect(curry_add(1,2,1)).toBe(4) })
咱們在index.js裏面實現一個curry函數
實現的時候須要注意幾個關鍵點
//index.js const curry = function(fn){ return function curried(...args){ //這裏不能用箭頭函數 if(fn.length===args.length){ return fn.apply(this,args) }else{ return function(...args1){ return curried.apply(this,args.concat(args1)) } } } } module.exports = { curry }
咱們跑一下測試用例,證實函數沒有問題。
看兩個柯理化的例子,加深一下理解
好比api長這樣 ajax(method,url,params)
// 咱們能夠在serve.js裏封裝一個post const post = url=> data => ajax('post',url,params) // 在module1api.js裏面封裝一些地址 import {post} from 'serve.js' const getList = post('www.xxx.com/api/xxx') // 在須要調接口的地方,咱們只用傳遞參數就好了,調用方式和地址已經提早穿過了 // 第一處地方 import{getList} from 'module1api.js' const data = getList(params) // 第二處地方 import{getList} from 'module1api.js' const data = getList(params) // 第N處地方... import{getList} from 'module1api.js' const data = getList(params)
拿到後臺的數據 常常要處理
好比原始數據 const data = [{name: 'kevin'}, {name: 'daisy'}]
咱們須要處理成['kevin','daisy']
每次在這都調用Map方法實際上代碼很臃腫
var _data = data.map(function (item) { return item.name; })
咱們其實能夠這麼寫,這也是利用了柯理化
const prop = curry(function (key, obj) { return obj[key] }); var _data = person.map(val=>prop('name')(val)) // var _data = person.map(prop('name')) /* *若是想直接這麼調的話,curry須要改一下, 把fn.length===args.length中的===改成>== 你們能夠好好想想緣由, */
柯理化其實挺經常使用的,不必定非要用curry函數,理解它的思想咱們就能寫出很優美很高效的代碼。
總歸就是閉包的一種應用。
柯理化
JavaScript專題之函數柯里化
lodash_curry
深刻高階函數應用之柯里化
https://segmentfault.com/a/1190000018180159