函数的组合

245 阅读3分钟

函数的组合,直接上代码

function compose(){
    var args = arguments;
    var first = arguments.length-1;
    return function(){
        var result = args[first].apply(null, arguments);
        var i = first - 1;
        while(i>=0){
            result = args[i].call(null, result);
            i--;
        }
        return result;
    }
}

const add = (x, y) => x + y + 4;
const mulatity = x => x * 4;
const toString = x => String(x);
const mySplit = arr => arr.split(",");
const myConsole = x => console.log(x);

const test = compose(myConsole, toString, mulatity, add);
test(1,3);
我们来分析整个过程:
  • 第一步的args
    ,需要注意的是这个args并不是真正的数组,而是一个类数组; 那么first就是 args这个类数组的长度= args.length-1 = 3;
  • test就是我们调用compose函数返回的一个函数;
    var test = function(){
        var result = args[first].apply(null, arguments);
        var i = first - 1;
        while(i>=0){
            result = args[i].call(null, result);
            i--;
        }
        return result;
    }
    
  • 然后我们传入(1,3);让我们看看 result 返回的是什么? args[first].apply(null,arguments)=>等于调用 result = add(1,3)=>1+3+4; result = 8;
  • 然后通过第一步传入函数的个数一次调用一个,并且把上一次调用的结果作为参数传入下一个被调用的函数;直到所有函数调用完毕
  • 也就是说函数的调用顺序是从后往前直到第一个为止;
  • 第二个result = 4*8 = 32;
  • 第三个result = 32.toString() = '32';
  • 直到第四步执行打印函数 打印到控制台 字符串类型的 ‘32’;
费这么大劲就弄这点东西,我为什么不直接这样写呢?
const garbageFun = (x,y) =>{
    console.log(((x+y+4)*4).toString());
}

牵扯到理论的东

  • 身为一个优秀的工程师,相信大家都听过这么一句话,优秀的代码都有这么一个特点 高内聚,低耦合 我们写代码的时候不只要完成业务,还要在这个过程中提升自己,提升自己就是要考虑整个程序的可扩展性,代码的健壮性,最重要的是什么?搞定不断变化的需求!!!
  • 如何提高代码的可扩展性,有这么一个概念,叫做 函数式编程,每一个函数只做一件事,每一个函数是纯函数,并且不会引起外部状态的变化,这样我们做业务的时候,只需要组合函数,就能搞定一部分需求了!
  • 是不是觉得枯燥无味,来见识一下改需求的威力,我需要将返回结果变为一个数组怎么做
//这是用组合函数的方法做的
const test = compose(myConsole, mySplit, toString, mulatity, add);
//这是常规思路的
const garbageFun = (x,y) =>{
   console.log([((x+y+4)*4).toString()]);
}

//来我们不需要在控制台打印了,我们需要给dom赋值了
//compose函数
const innerH = x => e.innerHTML = x;
const test = compose(innerH, mySplit, toString, mulatity, add);
//常规思路
const garbageFun = (x,y) =>{
   e.innerHTML = [((x+y+4)*4).toString()];
}

/*
拿着这个返回结果去发送ajax请求吧
*/
//组合函数,我们需要再定义两个函数,可以自己装一个http-server测试一下;
const ajax = data =>{
    return new Promise((resolve, reject)=>{
       //引入jquery或者使用原生的fetch都可以
       $.ajax({
           url:"./basic/index.txt",//写上你自己本地的某一个文件
           data,
           method:"get",
           success:(res)=>{
               resolve(res);
           }
       })
   })
};
const test= compose(ajax, mySplit, toString, mulatity, add);
test(1,3).then(res=>{
   console.log(res);//这里的res就是你要请求的东西
});

//普通的
const garbageFun = (x,y) =>{
  return [((x+y+4)*4).toString()];
}
const result = garbageFun(1,3);
ajax(result).then(res=>{
   console.log(res);//这里的res就是你要请求的东西
})

是不是觉得compose函数的的可扩展性和健壮性比常规思路【命令式编程】好多了,当然命令式编程的优点是容易理解,应付不断变化的需求就有点吃力了,理解了compose【函数式编程的一部分】,不仅有助于锻炼你的思维,掌握底层的一些东西,当你想掌握一门框架的时候,比如 react中的状态管理机 redux就会达到事半功倍的效果了,怎么样用函数式编程来编写你的代码吧!!!

附上 redux 的compose源码

function compose(...funs){
   if(funs.length == 0){
       return arg => arg;
   }
   
   if(funs.length ==1){
       return funs[0]
   }
   
   return funs.reduce((a,b)=>(...args)=>a(b(...args))
}