JavaScript專題之函數柯里化
JS 函數式編程指南html
不少人對於柯里化的理解僅僅停留在「複用參數」上。但我認爲函數式編程思想更重要做用的是:解除函數對執行時參數的依賴,加強函數的泛化能力,讓函數僅僅包含「純粹的操做邏輯」,這些操做邏輯要用在什麼樣的輸入上,使用函數時再決定。git
使用柯里化的場景:github
function getProp(obj, key)
)function getProp(obj, key) { return obj[key]; }
)獲得的函數就僅僅封裝了「操做邏輯」,函數對於操做的輸入不作任何假設,所以函數的泛化能力很強,能夠處理任何合法的輸入。(在這個例子中,getProp
能夠從任何對象中獲取任何屬性)編程
「不作任何假設」的說法其實不太準確,好比說getProp
就假設了obj
參數必須是對象,但這種假設是「完成操做邏輯」的必要要求,「不作任何多餘的假設」更準確一些。我在這裏使用更絕對的語氣,是爲了加強本身對這個觀點的印象。
getProp(obj1, 'key1')
和getProp(obj2, 'key2')
,函數能適應任何合法的輸入,無論調用多少次,無論傳入什麼參數,函數的操做邏輯都不會改變)let getPropFromArrProto = curry(getProp, Array.prototype);
經過這個新的函數就能直接從Array.prototype
中獲取屬性)function curry(fn, ...priorArgs) { const length = fn.length; return function judge(...restArgs) { return priorArgs.length + restArgs.length >= length ? fn.call(this, ...priorArgs, ...restArgs) : function (...args) { return judge.call(this, ...restArgs, ...args); } } } // 測試代碼 var fn = curry(function (a, b, c, d) { console.log([a, b, c, d]); return [a, b, c, d]; }, 'p'); fn("a", "b", "c") // [ 'p', 'a', 'b', 'c' ] fn("a", "b")("c") // [ 'p', 'a', 'b', 'c' ] fn("a")("b")("c") // [ 'p', 'a', 'b', 'c' ] fn("a")("b", "c") // [ 'p', 'a', 'b', 'c' ]
其中,ide
priorArgs.length + restArgs.length >= length ? fn.call(this, ...priorArgs, ...restArgs) : function (...args) { return judge.call(this, ...restArgs, ...args); }
它的意思是,若是已經接受的參數數量很多於fn
(被柯里化的函數)期待的參數數量,就調用fn並返回結果。
不然,返回一個新的函數,這個函數期待剩餘的參數。
調用這個新函數會再次進行參數數量的判斷,若是已經接受的參數數量很多於fn
(被柯里化的函數)期待的參數數量,就調用fn並返回結果,不然返回一個新的函數……以此類推。函數式編程