什麼是柯里化?
在計算機科學中,柯里化(英語:Currying),又譯為卡瑞化或加里化,是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,並且返回接受餘下的參數而且返回結果的新函數的技術。
以上是維基百科對於柯里化給出的定義,總結一下:
- 輸入是一個函數,並且這個函數擁有n個參數
- 輸出也是一個函數,並且可以使用
fn()()()這種方式調用 - 參數被柯里化過程中的函數被拆分
寫一個經典的用來解釋柯里化的例子:
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) {}這樣的函數我們很容易柯里化它
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);
}
}
}
那四個參數咋辦呢。。。很明顯這種方式並不具備通用性,其實仔細觀察上面的代碼,彷彿,似乎,可能遞歸能實現:
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);
}
}
}
以上就是關於柯里化的知識,希望對各位童鞋有所幫助。