維基百科中的定義:bash
在計算機科學中,柯里化(英語:Currying),又譯爲卡瑞化或加里化,是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,而且返回接受餘下的參數並且返回結果的新函數的技術。閉包
換句話說就是把一個有n個參數的函數轉換成n個嵌套的函數,每一個函數只接受一個參數,並返回一個新函數。也就是把f(a,b,c)
轉化爲f(a)(b)(c)
。函數
例如一個函數接受a, b, c三個參數,返回它們的乘積:ui
function multiply(a, b, c) {
return a * b * c;
}
複製代碼
運行此函數,咱們在參數中依次傳入1,2,3,返回6。this
multiply(1,2,3); // 6
複製代碼
讓咱們看一下柯里化以後的樣子:spa
function multiply(a) {
return (b) => {
return (c) => {
return a * b * c
}
}
}
multiply(1)(2)(3) // 6
複製代碼
咱們把multiply(1,2,3)
變成了multiply(1)(2)(3)
的形式。經過把一個多參函數轉換成一系列嵌套的函數,每一個函數依次接受一個參數,這就是函數柯里化。code
或者換一種寫法能夠更容易理解:ip
function multiply(a) {
return (b) => {
return (c) => {
return a * b * c
}
}
}
const mul1 = multiply(1);
const mul2 = mul1(2);
const result = mul2(3); // 6
複製代碼
multiply函數接受一個a參數,咱們傳入1。mult1
等於multiply(1)
就等於it
(b) => {
return (c) => {
return a * b * c
}
}
複製代碼
而且接受一個參數b。以此類推,mul1(2)
傳入2,而後賦值給mult2
等於io
(c) => {
return a * b * c
}
複製代碼
最後mul2(3)
返回a * b * c
。因爲閉包的特性會保存以前傳入的值1和2,最後得出6。
假設咱們有一個函數用來計算三個物體的體積。
function volume(l, w, h) {
return l * w * h;
}
volume(200,30,100) // 2003000
volume(32,45,100); //144000
volume(2322,232,100) // 53870400
複製代碼
從上面代碼能夠看出,若是每一個物體的高度都是100,咱們須要重複傳三次。 若是使用柯里化函數能夠避免:
function volume(h) {
return (w) => {
return (l) => {
return l * w * h
}
}
}
//固定高度
const itemHeight = volume(100);
//計算其餘不一樣狀況
itemHeight(30)(200);
itemHeight(45)(32);
itemHeight(232)(2322);
複製代碼
合成兩個函數的簡單代碼以下:
var compose = function(f,g) {
return function(x) {
return f(g(x));
};
};
複製代碼
f(x)
和g(x)
合成爲f(g(x))
,有一個隱藏的前提,就是f和g都只能接受一個參數, 其中就運用了函數柯里化。
Partial Application(偏函數應用)很容易和函數柯里化混淆,它是指使用一個函數並將其應用一個或多個參數,但不是所有參數,在這個過程當中建立一個新函數,這個函數用於接受剩餘的參數。這段話很不容易理解,具體看下面的例子:
function multiply(a,b,c){
return a * b * c;
}
//生產偏函數的工廠
function partial(fn,a){
return function(b,c){
return fn(a,b,c);
}
}
//變量parMulti接受返回的新函數
var parMulti = partial(multiply,1);
//在調用的時候傳入剩餘的參數
parMulti(2,3); // 6
複製代碼
partial
函數能夠幫咱們生成一個偏函數。partial
函數生成一個偏函數並賦值給parMulti
,其中預設一個值1
。parMulti
接受剩餘參數2,3
結合前面預設的1
得出最終結果。
例如bind函數可讓咱們傳入一個或多個想要預設的參數,以後返回一個新函數,並擁有指定的this值和預設參數。當綁定函數被調用時,這些參數會被插入到目標函數的參數列表的開始位置,傳遞給綁定函數的參數會跟在它們後面。
function addition(x, y) {
return x + y;
}
const plus5 = addition.bind(null, 5)
plus5(10) // output -> 15
plus5(20) // output -> 25
複製代碼
咱們預先傳入了參數5
,並返回了一個新函數賦值給plus5
,此函數能夠接受剩餘的參數。調用plus5
傳入剩餘參數10
得出最終結果15
,如傳入20
得出25
。偏函數經過設定預設值,幫咱們實現代碼上的複用。
柯里化和偏函數都是用於將多個參數函數,轉化爲接受更少參數函數的方法。傳入部分參數後,處於中間狀態的函數能夠做爲固定值進行復用。可是其中不一樣之處在於: