函數柯里化(curry)

前言

(話很少說,填以前的坑)數組

正文

引子-從apply說函數應用

在js裏,咱們對於function的用法,可能大部分狀況下都仍是處於調用,形如app

function add(x, y) {
    return x + y
}
console.log(add(1, 2)) //函數調用 返回3

可是有一個apply()函數,使咱們擁有另外一種方式來應用函數,例如函數

function add(x, y) {
    return x + y
}
console.log(add.apply(null, [1, 2])) //返回3

apply的第一個參數爲null時,this指向全局對象(忘記請自行查閱查mdn),在上面這個例子裏,經過apply來應用函數的時候,效果和調用函數徹底一致。this

部分應用

從前文可知,函數調用就是讓一個參數集合(前面的[1,2])應用到函數(前文的add函數)中,那部分應用就是考慮只傳遞部分參數,而非全部參數。 仍是上面add函數的例子,咱們但願實現下面的形式(在下一節具體實現):prototype

var newAdd = add.apply(null,[1])//部分應用 只傳遞了第一個參數
newAdd.apply(null,[2]) //3

分析上面的代碼可知,實現部分應用的關鍵是:部分應用的返回結果是一個新的函數,該函數能夠被傳入其餘參數再次調用code

柯里化(curry)

如今進入正題,前面講完了部分應用。curry化的含義,就是使函數理解並處理部分應用的過程對象

繼續按照上文的思路實現add函數的curry化:io

function add(x, y) {
    // 若是隻傳遞部分參數,則部分應用,返回一個新的函數
    if (y === undefined) {
      return function (y) {
        return x + y
      }
    }
    return x + y //若是傳遞全部參數,直接徹底應用
}
//運行前一節代碼
var newAdd = add.apply(null, [1])
console.log(newAdd.apply(null, [2])) //3
console.log(newAdd.apply(null, [5])) //6

上述代碼已經實現了前一節的要求,能夠看到curry的結果就是:通過一次curry的newadd函數,變成一個與1求和的函數,接應用的時候只傳遞一個參數,都能獲得對應的結果,同時也能夠看出這個curry太侷限。接下來咱們就要考慮,如何實現通用的curry函數console

通用curry函數

先回憶前面的過程,來思考curry一個函數的實現步驟:function

  1. 保存調用curry函數時傳入的參數,返回一個新函數(即柯里化執行結果)
  2. 結果函數在被調用後,要讓新的參數和舊的參數一塊兒應用的入參函數中

注:入參函數-要被curry的函數,結果函數-被curry以後的函數*

文字比較抽象,能夠直接看實如今回來看過程:

function commonCurry(fn) {
    var slice = Array.prototype.slice,
      storedArgs = slice.call(arguments, 1) //使用slice是爲了把arguments轉換成真正的數組,剝離此處第一個參數,是由於第一個參數是fn
    return function () {
      var newArgs = slice.call(arguments), //新傳入的參數
        args = storedArgs.concat(newArgs)
      return fn.apply(null, args)
    }
  }

  //使用舉例
  function add(a, b) {
    return a + b
  }
  var newAdd = commonCurry(add, 10)
  console.log(newAdd(5))
  
  // 多個參數
  function add2(a, b, c, d) {
    return a + b + c + d
  }
  var newAdd2 = commonCurry(add2, 10, 10)
  console.log(newAdd2(5, 4))//29
  
  // 屢次curry
  var newAdd3 = commonCurry(newAdd2, 10)
  console.log(newAdd3(10))//40

小結

以後會嘗試以更簡潔明瞭的方式來寫文章。若是內容有錯誤的地方歡迎指出(以爲看着不理解不舒服想吐槽也徹底沒問題);若是對你有幫助,歡迎點贊和收藏,轉載請徵得贊成後著明出處,若是有問題也歡迎私信交流,主頁添加了郵箱地址。

相關文章
相關標籤/搜索