了解如何在vanilla JavaScript中实现lodash的_.flowRight

时间:2017-12-02 14:48:59

标签: javascript recursion closures lodash

在学校,我们的任务是建立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 个答案:

答案 0 :(得分:4)

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

这使用spreadrestreduce

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'));

答案 1 :(得分:4)

要从右向左流动,您可以使用...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'));




答案 2 :(得分:1)

下面写的函数中的想法是返回一个函数,该函数将遍历函数列表并存储每个调用的结果并在结束时返回它。

function flowRight(...args) {
    return function (initial) {
        let value = initial;

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

        return value;   
    };
}

答案 3 :(得分:1)

从右到左的构图

const compose = (f,...fs) => x =>
  f === undefined ? x : f(compose(...fs)(x))

从左到右的构图

const compose = (f,...fs) => x =>
  f === undefined ? x : compose(...fs)(f(x))