函式柯里化
-
柯里化
在電腦科學中,柯里化(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個,所以返回結果了,已經不是函式