zoukankan      html  css  js  c++  java
  • JS高阶编程技巧--compose函数

    先看代码:

    let fn1 = function (x) {
        return x + 10;
    };
    let fn2 = function (x) {
        return x * 10;
    };
    let fn3 = function (x) {
        return x / 10;
    };
      console.log(fn3(fn1(fn2(fn1(6)))));

    这是几个简单的运算方法,但想输出的是一个多层函数嵌套的运行结果,即把前一个函数的运行结果赋值给后一个函数,当然我们可以写成一下这样:

    let x = fn1(6);
    x = fn2(x);
    x = fn1(x);
    x = fn3(x);

    但现在我就想用一个函数解决这种问题,形如:

    compose(fn1, fn2, fn1, fn3)(6);

    这个compose函数就是这篇文章介绍的——函数调用的扁平化,即把层级嵌套的那种函数调用(一个函数的运行结果当作实参传给下一个函数的这种操作)扁平化,这就是compose函数。

    那么下面就是开始实现这个函数:

    首先我们看参数,需要给出不确定个数的函数:

    function compose(...funcs) {
        //=>funcs:传递的函数集合
    }

    compose函数执行后跟个(),说明函数执行完再执行一个函数,即函数执行完会返回一个新函数,而且也会给出第一次调用函数时的参数:

    function compose(...funcs) {
        //=>funcs:传递的函数集合
        return function proxy(...args) { 
          //=>args:第一次调用函数传递的参数集合
    
        }    
    }

    继续往下进行,我们需要判断给出的函数集合的个数,如果没有给函数,我们只需将后一个的参数返回,如果只给出一个函数,我们只需把后一个的参数赋给这个函数去执行即可:

    function compose(...funcs) {
        //=>funcs:传递的函数集合
        return function proxy(...args) {
            //=>args:第一次调用函数传递的参数集合
            let len = funcs.length;
            if (len === 0) {
                //=>一个函数都不需要执行,直接返回ARGS
                return args;
            }
            if (len === 1) {
                //=>只需要执行一个函数,把函数执行,把其结果返回即可
                return funcs[0](...args);
            }
    
        };
    }

    如果给出的参数集合是两个及以上,那就是把前一个函数的执行结果赋给后一个函数,说到这,应该会想到一个满足这个需求的数组方法——reduce:

    function compose(...funcs) {
        //=>funcs:传递的函数集合
        return function proxy(...args) {
            //=>args:第一次调用函数传递的参数集合
            let len = funcs.length;
            if (len === 0) {
                //=>一个函数都不需要执行,直接返回ARGS
                return args;
            }
            if (len === 1) {
                //=>只需要执行一个函数,把函数执行,把其结果返回即可
                return funcs[0](...args);
            }
            return funcs.reduce((x, y) => {
            
            });
        };
    }

    但这里需要注意的是,第一次执行的时候,参数x是个函数,之后再执行的时候x是个函数执行的结果,所以需要进行判断:

    function compose(...funcs) {
        //=>funcs:传递的函数集合
        return function proxy(...args) {
            //=>args:第一次调用函数传递的参数集合
            let len = funcs.length;
            if (len === 0) {
                //=>一个函数都不需要执行,直接返回ARGS
                return args;
            }
            if (len === 1) {
                //=>只需要执行一个函数,把函数执行,把其结果返回即可
                return funcs[0](...args);
            }
            return funcs.reduce((x, y) => {
                return typeof x === "function" ? y(x(...args)) : y(x)
            });
        };
    }

    这样,compose函数完成。

    当然,redux源码中的compose.js也可以实现一开始想要的效果:

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

    但它和我们写的compose函数有些不同,它执行的顺序是函数集合中的函数从后往前执行,所以结果也会不同:

    compose(fn1, fn2, fn1, fn3)(6)); //=> 用第一个compose执行的结果是17,用redux的执行结果是116
  • 相关阅读:
    NX二次开发-获得制图中对象的坐标点UF_DRF_ask_origin
    string的find("")
    NX二次开发-设置尺寸的附加尺寸UF_DRF_set_appended_text
    NX二次开发-获取尺寸的附加文本UF_DRF_ask_appended_text
    NX二次开发-更改图纸尺寸内容(编辑文本)uc5566
    NX二次开发-获取工程图尺寸的值UF_DRF_ask_dim_info
    MFC进度条
    NX二次开发-对话框解锁UF_UI_unlock_ug_access
    NX二次开发-对话框加锁UF_UI_lock_ug_access
    <转载>深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别
  • 原文地址:https://www.cnblogs.com/ronaldo9ph/p/12323026.html
Copyright © 2011-2022 走看看