JS:函數柯里化


函數柯里化

  1. 柯里化

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM