函数组合javascript

函数组合javascript,javascript,functional-programming,Javascript,Functional Programming,我试图理解Javascript中的函数组合,并遵循 我尝试了下面的程序,该程序将接受一个句子,将其分成若干部分(由空格分隔),并在每个单词上使用大写字母,然后返回一个单词数组 function compose(f, g) { "use strict"; return function() { return f.call(this, g.apply(this,arguments)); } } var split = function (string, de

我试图理解Javascript中的函数组合,并遵循

我尝试了下面的程序,该程序将接受一个句子,将其分成若干部分(由空格分隔),并在每个单词上使用大写字母,然后返回一个单词数组

function compose(f, g) {
    "use strict";
    return function() {
        return f.call(this, g.apply(this,arguments));
    }
}

var split = function (string, delim) {
    "use strict";
    return string.split(delim);
};

var uppercase = function (string) {
    "use strict";
    if (string instanceof Array) {
        return string.map(function (x) {
            return x.toString().toUpperCase();
        });
    } else {
        return string.toString().toUpperCase();
    }

    //return string.toString().toUpperCase();
};

var myfunc = compose(uppercase,split);

var data = myfunc("Elementary! My dear Watson",/\s+/);
console.log(data);
虽然我得到了我想要的,但代码在以下方面很难看:

  • 我必须重新定义split和toUpperCase,因为我一直在 “引用错误:toUpperCase未定义”。是因为他们是 方法,而不是纯函数本身
  • 大写方法很难看,因为它应该只接收一个字符串,以便翻转大小写,但是因为我正在标记它,所以这个函数接收一个数组,从而进行难看数组检查

  • 如何即兴编写代码以获得“功能管道”,即。拆分->映射->大写?

    下面是一个小示例,介绍如何启动并运行一个流畅的界面,涵盖问题的第三部分。关键的一点是使用
    newobj
    创建一个对象,在方法中,您需要
    返回该对象以允许方法链接

    Functional Javascript不允许使用链接方法,因为它没有内部状态,您可以使用Functional js来修饰和混合可以返回值或其他函数的其他函数

    //MyObj在模块内声明,以使内部私有
    var myObj=(函数(){
    //构造函数
    函数MyObj(字符串,delim){
    this.input=字符串;
    this.delim=delim;
    }
    //在其原型上创建MyObj方法
    //所有方法都使用fluent函数进行了修饰
    MyObj.prototype={
    //拆分输入
    拆分:流畅(函数(delim){
    如果(!Array.isArray(this.input)){
    this.input=this.input.split(delim!=null?delim:this.delim);
    }
    }),
    //将文本转换为大写
    大写:fluent(function(){
    if(Array.isArray(this.input)){
    this.input=this.input.map(函数(字符串){
    返回字符串.toUpperCase();
    });
    }否则{
    this.input=this.input.toUpperCase();
    }
    }),
    //反转阵列
    反向:fluent(函数(){
    if(Array.isArray(this.input)){
    this.input=this.input.reverse();
    }
    否则{
    this.input=this.input.split(“”).reverse().join(“”);
    }
    }),
    //如果你使用的是流畅的界面,或者决定你的终点是什么,你需要一个getter
    get:function(){
    返回此.input;
    }
    }
    返回函数构造函数(字符串,delim){
    返回新的MyObj(字符串,delim);
    }
    })();
    //myObj是创建myObj的函数
    console.log(myObj);
    log(myObj(“基本的!我亲爱的Watson)”,/\s+/).split().uppercase().get());
    //使用该代码,您可以覆盖默认的delimeter
    console.log(myObj(“初等!我亲爱的Watson)”,/\s+/).split(“”).uppercase().get());
    //运行不同的方法
    log(myObj(“基本的!我亲爱的Watson)”,/\s+/).split().uppercase().reverse().get());
    //秩序不再重要
    log(myObj(“基本的!我亲爱的Watson)”,/\s+/).reverse().uppercase().split().get());
    //MyObj还有一个内部状态,因此您可以
    //函数装饰器-这将使原型方法返回一个值或
    函数fluent(方法){
    返回函数(){
    var ret=method.apply(这是参数);
    return ret!=null
    ?ret
    :这个;
    }
    }

    这里的代码与您使用的代码类型相同,并且经过了一些简化。如果这是你想要的编码方向,我不能推荐Reg Braith的Javascript Allonge等等,它完全改变了我编写代码的想法

    希望这个小例子展示了如何组合函数,以及函数js是多么有用。另一个很大的好处是,如果您使用的纯函数不考虑外部范围,那么您可以轻松地调试问题,因为您可以遵循可靠的函数调用流

    我花了大约6个月的时间和不断的实践,学习了足够多的功能,以便能够理解它的基本概念。但这是非常值得的努力

    “严格使用”//您只需要对HHOLE文件进行一次严格的使用
    //对于compose,您不应该真正需要调用或应用,因为这始终是纯函数的窗口
    函数组合(a,b){
    返回函数(c){
    返回a(b(c));
    }
    }
    //split现在是一个简单的函数,它接受delimeter并返回一个拆分字符串的函数
    功能拆分(delim){
    返回函数(字符串){
    返回字符串.split(delim);
    }
    };
    //如果您添加一个函数映射器,您可以消除一些大写的复杂性
    //并用大写字母组成地图
    功能图(fn){
    返回函数(arr){
    返回Array.prototype.map.call(arr,fn);
    }
    }
    //这是一个非常简单的单一责任函数,可以由
    函数大写(字符串){
    返回字符串.toUpperCase();
    };
    变量
    splitBySpace=split(/\s+/),
    arrToUpper=map(大写),
    myfunc=组合(arrToUpper,splitBySpace);
    log(arrToUpper(['one','two']);
    log(myfunc(“初等!我亲爱的沃森”);
    //如果要在不同的字符上拆分,则需要通过使用不同的delimeter创建新的拆分函数
    变量
    splitByChar=split(“”),
    splitByBang=split(“!”);
    //您也不必编写函数,您可以正常地编写它们,但要遵循这些函数要困难得多。
    log(map(大写)(拆分(“”)(“初等!我亲爱的沃森”)
    
    函数组合就是将两个或多个函数组合成一个函数。我已经写了一个很容易理解的东西,我想它会为你澄清很多事情

    然而,您想要的是非常不同的东西,并且在javascript中非常直接

    "Elementary! My dear Watson".split(/\s+/).map(val => val.toUpperCase());
    
    <
    function myFunct(str, delim) {
        str.split(delim).map(val => val.toUpperCase());
    }
    
    const SALES_TAX = 0.08;
    const COUPON_CODES = {
      AAAA: 0.1,
      BBBB: 0.07,
      CCCC: 0.15,
    };
    
    const shoppingtotal = shoppingCart =>
      shoppingCart.reduce((acc, item) => {
        acc += item.price * item.qty;
        return acc;
      }, 0);
    const discount = couponCode => amount =>
      amount * (1 - COUPON_CODES[couponCode]);
    const tax = amt => amt * (1 + SALES_TAX);
    
    const compose = fns => input => fns.reduce((acc, fn) => fn(acc), input);
    const calculatePayment = compose([shoppingtotal, discount('AAAA'), tax]);
    
    calculatePayment([
    {
      name: 'pencil',
      price: 1,
      qty: 2,
    },
    {
      name: 'Pen',
      price: 1.5,
      qty: 20,
    },
    {
      name: 'Eraser',
      price: 0.25,
      qty: 10,
    }])