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

JavaScript 函數(shù)合成

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

■設(shè)計思路

在函數(shù)式編程中,經(jīng)常見到如下表達(dá)式運(yùn)算:

    a(b(c(x)));

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

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

f (x);

例如:

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

    return function (x) {

        return f(g (x));

    };

};

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

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

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

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


■實例設(shè)計

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

【實現(xiàn)代碼】

//函數(shù)合成,從右到左合成函數(shù) 

var compose = function () {

    var _arguments = arguments;           //緩存外層參數(shù)

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

    var index = length;                   //定義游標(biāo)變量

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

    while (index--) {

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

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

       }

    }

    return function () {

        var index = length-1;    //定位到最后一個參數(shù)下標(biāo)

        //如果存在2個及以上參數(shù),則調(diào)用最后一個參數(shù)函數(shù),并傳入內(nèi)層參數(shù) 

        //否則直接返回第1個參數(shù)函數(shù)

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

        //迭代參數(shù)函數(shù)

        while ( index——){

            //把右側(cè)函數(shù)的執(zhí)行結(jié)果作為參數(shù)傳給左側(cè)參數(shù)函數(shù),并調(diào)用 

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

        }

        return result; //返回最左側(cè)參數(shù)函數(shù)的執(zhí)行結(jié)果

    }

}

//反向函數(shù)合成,即從左到右合成函數(shù) 

var composeLeft = function () {

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

}

【應(yīng)用代碼】

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

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

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

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

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

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ù)查找其他問題的答案?

相關(guān)視頻回答
回復(fù)(0)
返回頂部