代码之家  ›  专栏  ›  技术社区  ›  Antonio Pavicevac-Ortiz

了解如何实施lodash的。vanilla JavaScript中的flowRight

  •  6
  • Antonio Pavicevac-Ortiz  · 技术社区  · 8 年前

    在学校,我们的任务是建立一个 lodash method flowRight!

    规范中提到:

    接受任意数量的函数并返回一个新函数 使用其参数并从右到左调用提供的函数 (从最后到第一)。每个函数(第一个函数除外)的参数为 由函数右侧的返回值确定。电话 对于flowRight返回的函数,计算结果为的返回值 最左边的功能。

    他们举了一个例子:

    e.g.
    
    var sayHello = function (name) {
        return 'Hello, ' + name;
    },
    
    addExclamation = function (s) {
        return s + '!';
    },
    
    smallTalk = function (s) {
        return s + ' Nice weather we are having, eh?';
    };
    
    var greetEnthusiastically = flowRight(addExclamation, sayHello);
    
    greetEnthusiastically('Antonio');
    // --> returns 'Hello, Antonio!'
    //(sayHello is called with 'Antonio', 
    //  addExclamation is called with 'Hello, Antonio')
    

    我觉得我理解了一个静态示例中发生的事情,就像这个示例所演示的那样。

    function (func1, func2) {
        return function(value) {
            return func1(func2(value));
        }
    }
    

    我想我很难把我的大脑绕成一个循环,我想这是你需要的。这是到目前为止我的实现。

    var flowRight = function (...args) {
        var Func;
        for(var i = args.length - 2; 0 > i; i--) {
            function Func(value) {
                return args[i](args[i + 1](value));
            }
        }
        return Func;
    };
    

    任何帮助都将不胜感激!

    4 回复  |  直到 8 年前
        1
  •  8
  •   kemotoe    8 年前

    不需要循环。如果允许,则使用ES6。

    这使用 spread , rest reduce

    const flowRight = (...functions) => functions.reduce((a, c) => (...args) => a(c(...args)));
    

    下面的示例

    var sayHello = function (name) {
      return 'Hello, ' + name;
     },
    
    addExclamation = function (s) {
      return s + '!';
    },
    
    smallTalk = function (s) {
      return s + ' Nice weather we are having, eh?';
    }
    
    const flowRight = (...functions) => functions.reduce((a, c) => (...args) => a(c(...args)))
    
    var greetEnthusiastically = flowRight(smallTalk, addExclamation, sayHello)
    
    console.log(greetEnthusiastically('Antonio'));
        2
  •  5
  •   subhaze    8 年前

    要从右向左流动,可以使用 ...spread 具有 .reduceRight(x, y)

    我对下面的代码进行了注释,试图解释这一切是如何协同工作的。

    const sayHello = function (name) {
      return 'Hello, ' + name;
     };
    
    const addExclamation = function (s) {
      return s + '!';
    };
    
    const smallTalk = function (s) {
      return s + ' Nice weather we are having, eh?';
    }
    
    // function that takes functions and then
    // returns a function that takes  a value to apply to those functions in reverse
    const flowRight = (...fns) => val => fns.reduceRight((val, fn) => {
      // return the function and pass in the seed value or the value of the pervious fn.
      // You can think of it like the following.
      // 1st pass: sayHello(value) -> "Hello, " + value;
      // 2nd pass: addExclamation("Hello,  $value") -> "Hello,  $value" + "!";
      // 3rd pass: smallTalk("Hello,  $value!") -> "Hello,  $value!" + ' Nice weather we are having, eh?'
      // ... and so on, the reducer will keep calling the next fn with the previously returned value
      return fn(val)
    // seed the reducer with the value passed in
    }, val);
    
    var greetEnthusiastically = flowRight(smallTalk, addExclamation, sayHello);
    
    console.log(greetEnthusiastically('Antonio'));
        3
  •  2
  •   Mulan    5 年前

    从右向左合成

    const flowRight = (f, ...more) => x =>
      f == null ? x : f(flowRight(...more)(x))
    
    const upper = s =>
      s.toUpperCase()
    
    const greeting = s =>
      `Hello, ${s}`
    
    const addQuotes = s =>
      `"${s}"`
    
    const sayHello =
      flowRight(addQuotes, greeting, upper)
    
    console.log(sayHello("world"))
    // "Hello, WORLD"

    从左向右合成

    const flowLeft = (f, ...more) => x =>
      f == null ? x : flowLeft(...more)(f(x))
    
    const upper = s =>
      s.toUpperCase()
    
    const greeting = s =>
      `Hello, ${s}`
    
    const addQuotes = s =>
      `"${s}"`
    
    const sayHello =
      flowLeft(addQuotes, greeting, upper)
    
    console.log(sayHello("world"))
    // HELLO, "WORLD"

    使用reduceRight

    我们可以使用 reduceRight 易于实施 flowRight -

    const flowRight = (...fs) => init =>
      fs.reduceRight((x, f) => f(x), init)
    
    const upper = s =>
      s.toUpperCase()
    
    const greeting = s =>
      `Hello, ${s}`
    
    const addQuotes = s =>
      `"${s}"`
    
    const sayHello =
      flowRight(addQuotes, greeting, upper)
    
    console.log(sayHello("world"))
    // "Hello, WORLD"

    使用reduce

    或者我们可以使用 reduce 易于实施 流动性 -

    const flowLeft = (...fs) => init =>
      fs.reduce((x, f) => f(x), init)
    
    const upper = s =>
      s.toUpperCase()
    
    const greeting = s =>
      `Hello, ${s}`
    
    const addQuotes = s =>
      `"${s}"`
    
    const sayHello =
      flowLeft(addQuotes, greeting, upper)
    
    console.log(sayHello("world"))
    // HELLO, "WORLD"
        4
  •  1
  •   Александр Буклей    8 年前

    下面编写的函数的思想是返回一个函数,该函数将遍历函数列表,存储每次调用的结果,并在最后返回。

    function flowRight(...args) {
        return function (initial) {
            let value = initial;
    
            for (let i = args.length - 1; i >= 0; i--) {
                value = args[i](value);
            }
    
            return value;   
        };
    }