函數柯里化的理解和實現

什麼是柯里化?

在計算機科學中,柯里化(英語:Currying),又譯爲卡瑞化或加里化,是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,而且返回接受餘下的參數並且返回結果的新函數的技術。

以上是維基百科對於柯里化給出的定義,總結一下:javascript

  • 輸入是一個函數,而且這個函數擁有n個參數
  • 輸出也是一個函數,而且能夠使用fn()()()這種方式調用
  • 參數被柯里化過程當中的函數被拆分

寫一個經典的用來解釋柯里化的例子:java

function add(a, b, c) {
    return a + b + c;
}

const addTen = curry(add, 10); // curry就是後續咱們將實現的 柯里化函數
addTen(1)(2) // 13
addTen(3, 4) // 17

不難看出柯里化的用途之一就是參數複用,咱們能夠經過柯里化的方式很方便的實現參數複用,可能這樣你感受沒啥卵用,再來看下面例子:數組

const amount = [
    { deposit: 120, finalPayment: 200 },
    { deposit: 110, finalPayment: 300 },
    { deposit: 130, finalPayment: 100 },
];

// 按照deposit的值對數組進行排序
// 很容易想到這麼作
amount.slice().sort((a, b) => a.deposit - b.deposit);
// 後來又須要對finalPayment進行排序
amount.slice().sort((a, b) => a.finalPayment - b.finalPayment);

// 咱們再來使用柯里化的形式從新寫一下
const sort = curry(function(field, a, b) {
    return a[field] - b[field];
})
console.log(amount.slice().sort(sort('deposit'))); // deposit進行排序
console.log(amount.slice().sort(sort('finalPayment'))); // finalPayment進行排序

簡而言之:JavaScript中的柯里化實際上是利用閉包的特性,將全部參數都蒐集到以後再一併執行。閉包

function fn(a, b, c, d, e...) {}
// 經過柯里化 轉換爲
curryFn(a)(b)(c)(d)(e)(...)

如何實現柯里化?

對於add(a, b) {}這樣的函數咱們很容易柯里化它app

function add(a, b) {
    return a + b;
}

function curry(fn, a) {
    return function(b) {
        return fn(a, b);
    }
}

curry(add, 10)(1); // 11

沒啥毛病,那我想作一個傳入三個參數的函數柯里化咋辦呢?安排~函數

function curry(fn, a) {
    return function(b) {
        return function(c) {
            return fn(a, b, c);
        }
    }
}

那四個參數咋辦呢。。。很明顯這種方式並不具有通用性,其實仔細觀察上面的代碼,彷彿,彷佛,可能遞歸能實現:this

function curry(fn, ...args) {
    return function(...innerArgs) {
        const allArgs = [...args, ...innerArgs];
        
        if (fn.length <= allArgs.length) {
            // 說明已經接受完全部參數,這個時候能夠執行了
            return fn.apply(this, allArgs);
        } else {
            // 繼續返回函數,收集參數
            return curry(fn, ...allArgs);
        }
    }
}

以上就是關於柯里化的知識,但願對各位童鞋有所幫助。code

相關文章
相關標籤/搜索