稍微激進的標題可能會致使標題黨誤讀了這篇博客。我要澄清一下:我本人喜歡函數式編程。個人主要觀點是:
JavaScript最好的特性之一就是能夠適用多種不一樣的編程風格。所以:若是你Currying編程到沒有任何提到的替代品適合你,那麼你就肆意適用Curring吧。 若是你這樣作,請保持你的代碼風格一致。而且準備好你的代碼與生態系統的其餘部分稍有不一樣。javascript
Currying在函數式編程中是一種流行的技術, 它有助於偏函數應用。html
其思想以下:若是您不爲函數提供全部參數,則返回一個函數。函數的入參是剩餘參數,其輸出是原始函數的結果。java
例如,若是想要數組的全部元素加2,並有一個二進制函數Add(x,y),則能夠以下所示:git
const arr = [1, 2, 3]; arr.map(add(2)); // [3, 4, 5]`
順便說一下,具備自動currying的函數式編程語言一般具備能夠這樣使用的加法操做符。es6
你有兩個選擇執行add()方法來支持currying。github
ES6箭頭函數能夠很容易地手動編寫柯里函數:編程
const add = x => y => x + y; // 等價於(譯者注) function add(x) { return function(y) { return x + y; } }
以下所示你能夠這樣執行add()數組
add(2)(3); // 5
一個函數持有多個須要轉化的嵌套函數,多數具備自動currying的函數式編程語言在語法上add(1, 2) 和add(1)(2)沒有什麼區別。app
2.2 重載 currying編程語言
一些庫提供了重載的函數。 根據參數數量,這些重載函數中的每個都會有不一樣的表現:
這種形式的curring的實現以下。
function add(...args) { if (args.length < 2) { return add.bind(this, ...args); } const [x, y] = args; return x + y; }
能夠編寫一個工具函數,將普通函數轉換爲這種實現。
柯里化是一種有助於偏函數應用的函數轉化技術。
若是想要在JavaScript使用currying編程你有兩選擇:
使用真currying
使用重載currying
若是你轉換了內置函數或方法來適應你的currying風格,那麼你將面對不少問題。
注意:並不是全部這些缺點一樣重要。
javascript中具名參數能夠經過Object字面量模擬(Simulating named parameters ES6中)我喜歡這種綁定參數的方式,他使得代碼更有自我描述性。不是全部currying的javascript庫都支持具名參數。
一般狀況下在函數的後面使用()就能夠執行該函數。Currying後你必須清楚的知道函數函數foo中函數的個數。以便知道 foo(123)執行後獲得的是一個函數仍是函數的結果。
比較下面兩個偏函數應用
foo(123, ?) _ => foo(123, _)
foo()支持多種方式調用。
使用具名參數,在curry中會丟失更多信息
arr.map(findCity({ latitude: 48.137154 })); // curried arr.map(_ => findCity({ latitude: 48.137154, longitude: _ }))
靜態類型系統(TypeScript,Flow,...)會減小錯誤,可是替代方法仍然更易於閱讀。
若是忽略參數,就會使用函數的默認參數
function add(x=0, y=0) { return x + y; }
默認參數可使的添加參數更加透明而且不會破壞現有調用,這種技術對命名參數特別有用,我常常用來保證通用函數和方法的適用性。
使用參數默認值省略參數意味着使用默認值,使用currying省略參數意味着返回偏函數, 所以二者有衝突。
使用Currying,參數對函數開始是對配置和結束運算都很重要。而Javascript中並非這樣。
例如parseInt()的簽名是:
parseInt(s : string, radix : number);
這使得它不可能這樣預先填充基數:
['32', '17', '5'].map(parseInt(10)) // doesn’t work
當談到Currying,人們一般想要的是偏函數編程。讓咱們看看下面的例子重載Currying並探索替代方案。
[1, 2, 3].map(add(2))
替代 1: .bind().
[1, 2, 3].map(add.bind(null, 2))
替代 2: arrow functions.
[1, 2, 3].map(x => add(2, x))
替代 3: an upcoming proposal for partial application.
[1, 2, 3].map(add(2, ?))
注:語法固定,提案處於早期階段。
這個建議的好處在於,它能夠很好地處理任意的簽名,而且具備很好的描述性語法。