位置:首頁 > 軟件操作教程 > 編程開發(fā) > JavaScript > 問題詳情

JavaScript 函數合成

提問人:劉團圓發(fā)布時間:2020-11-25

■設計思路

在函數式編程中,經常見到如下表達式運算:

    a(b(c(x)));

這是“包菜式”多層函數調用,但不是很優(yōu)雅。為了解決函數多層調用的嵌套問題,我們需要用到函數合成。函數合成的語法形式如下:

var f = compose (a, b, c);        //合成函數

f (x);

例如:

var compose = function (f, g) {        //兩個函數合成

    return function (x) {

        return f(g (x));

    };

};

var add = function (x) { return x + 1;}       //加法運算

var mul = function (x) { return x * 5;}       //乘法運算

compose (mul, add) (2) ;         //合并加法運算和乘法運算,返回15

    在上面的代碼中,compose函數的作用就是組合函數,將函數串聯(lián)起來執(zhí)行,將多個函數組合起來,一個函數的輸出結果是另一個函數的輸入參數,一旦第一個函數開始執(zhí)行,就會像多米諾骨牌一樣 推導執(zhí)行了。


■實例設計

    下面來完善compose實現,實現無限函數合成。設計思路:既然函數像多米諾骨牌式的執(zhí)行,可以使用遞歸或迭代,在函數體內不斷地執(zhí)行arguments中的函數,將上一個函數的執(zhí)行結果作為下一個執(zhí)行函數的輸入參數。

【實現代碼】

//函數合成,從右到左合成函數 

var compose = function () {

    var _arguments = arguments;           //緩存外層參數

    var length = _arguments. length;      //緩存長度

    var index = length;                   //定義游標變量

    //檢測參數,如果存在非函數參數,則拋出異常 

    while (index--) {

       if (typeof —arguments[index] !== 'function') { 

           throw new TypeError (’ 參數必須為函數!');

       }

    }

    return function () {

        var index = length-1;    //定位到最后一個參數下標

        //如果存在2個及以上參數,則調用最后一個參數函數,并傳入內層參數 

        //否則直接返回第1個參數函數

        var result = length ?_arguments[index].apply(this, arguments) : arguments[0];

        //迭代參數函數

        while ( index——){

            //把右側函數的執(zhí)行結果作為參數傳給左側參數函數,并調用 

            result = —arguments[index]?call(this, result);

        }

        return result; //返回最左側參數函數的執(zhí)行結果

    }

}

//反向函數合成,即從左到右合成函數 

var composeLeft = function () {

    return compose.apply(null, [].reverse.call ( arguments));

}

【應用代碼】

    在上面的實現代碼中,composeO函數是根據參數順序,從右到左進行合成,當然也可以把參數函數按從左到右進行合成,實現代碼參考composeLeft()函數;同時在compose體內添加了一層函數的校驗,允許傳遞一個或多個參數。

var add = function (x) { return x + 5; } //加法運算

var mul = function (x) { return x * 5; } //乘法運算

var sub = function (x) { return x - 5; } //減法運算

var div = function (x) { return x / 5; } //除法運算

var fn = compose(add, mul, sub, div);

console.log (fn (50) ) ;                 //返回30

var fn = compose(add, compose(mul, sub, div));

console.log (fn (50) ) ;                 //返回30

var fn = compose(compose(add, mul), sub, div);

console.log (fn (50) ) ;                 //返回30

上面幾種組合方式都可以返回30。注意,排列順序要保持一致。

繼續(xù)查找其他問題的答案?

相關視頻回答
回復(0)
返回頂部