函數柯里化
-
柯里化
在計算機科學中,柯里化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,並且返回接受余下的參數且返回結果的新函數的技術。
簡單來說,就是固定一些參數,返回一個接受剩余參數的函數。
其實就是使用閉包返回一個延遲執行函數。
只看文字描述去理解柯里化可能有點難,舉一個很經典的例子:
// 這個例子是柯里化,也可以說是部分應用 // 對於什么是部分應用,這里不進行探討 function add(num1, num2) { return num1 + num2; } function curry(func) { let args = [].slice.call(arguments, 1); return function() { let innerArgs = [].slice.call(arguments); let finalArgs = [...args, ...innerArgs]; return func.apply(null, finalArgs); } } // 得到延遲執行函數 let curriedAdd = curry(add, 5); // 可以多次復用得到的函數 curriedAdd(1); // 6 curriedAdd(2); // 7
看了上面簡單的例子,現在來實現能這樣使用
curriedAdd(1)(2, 3)(4)
的柯里化函數:function aidCurry(func) { let args = [].slice.call(arguments, 1); return function() { return func.apply(null, [...args, ...arguments]); } } function curry(func, length) { length = length || func.length; return function() { // 傳入參數為 0,表示返回結果 if (arguments.length != 0 && arguments.length < length) { let finalArgs = [func, ...arguments]; // 參數的數量不足時,利用閉包將已傳入參數存儲起來 return curry(aidCurry.apply(null, finalArgs), length - arguments.length); } else { // 參數數量夠了或者中途結束,則返回結果 return func.apply(null, arguments); } }; } // length 為 4,表示當傳入參數到達4個時返回結果 let curriedAdd = curry(function add() { return [...arguments].reduce((acc, cur) => acc + cur); }, 4); // 傳入參數為4個 curriedAdd(1)(2, 3)(4); // 10 // 中途結束 curriedAdd(1)(2, 3)(); // 6 // error: not a function curriedAdd(1)(2)()(3); // 使用 (),就表示返回結果,已經不是函數 curriedAdd(1)(2, 3)(4)(); // 傳入參數已經為4個,所以返回結果了,已經不是函數