繁体   English   中英

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

[英]Understanding how to implement lodash's _.flowRight in vanilla JavaScript

在学校,我们的任务是构建lodash 方法 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;
};

任何帮助将不胜感激!

不需要循环。 如果允许,这将使用 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'));

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

从右到左的组合

 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来轻松实现flowRight

 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"

下面编写的函数中的想法是返回一个函数,该函数将迭代函数列表并存储每次调用的结果并在最后返回它。

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

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

        return value;   
    };
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM