首页 > 解决方案 > 使用reduce方法进行管道

问题描述

trincot 在 2016 年 10 月发表了一篇关于使用 reduce 方法构建管道函数的优秀帖子(链接到发布),我正在尝试详细了解代码。

ES6 版本

function piper(...fs) {
    return (...args) => fs.reduce((args,f) => [f.apply(this,args)],args)[0];
}

具体来说:
1. 代替[f.apply(this.args)],f(...args)也有效,但f(args)无效。为什么不起作用f(args)
2.关于内部(匿名)“reduce”函数中的第二个参数,为什么args甚至是必要的?. . .,即为什么下面的代码不起作用?

function piper(...fs) {
    return (...args) => fs.reduce((args,f) => [f.apply(this,args)])[0];
}

B. 或者,为什么我们不能只使用[]作为参数而不是args

function piper(...fs) {
    return (...args) => fs.reduce((args,f) => [f.apply(this,args)],[])[0];
}

ES5 版本

function piper(/* functions */) {
    var fs = [].slice.apply(arguments);    
    return function (/* arguments */) { 
        return fs.reduce(function (args,f) {
            return [f.apply(this,args)];
        }.bind(this), [].slice.apply(arguments))[0];
    }.bind(this);
}

问题: 1. 在内部(匿名)reduce函数中,为什么我们需要第二个参数[].slice.apply(arguments)?即,为什么不能[]代替它工作?
2. 或者,为什么我们不能完全忽略这个参数?

非常感谢您帮助我更深入地了解这些问题。

标签: javascript

解决方案


args作为第二个参数传递给函数reduce需要指定累加器(即变量)的初始值args,以便在第一次迭代时,

fs.reduce((args,f) =>

结果args是初始参数(如预期的那样)。否则,如果不将初始值传递给.reduce, 的初始值args将是数组中的第一项fns,这绝对不是您想要的:

function piper(...fs) {
    return (...args) => fs.reduce((args,f) => {
      console.log(args);
      return [f.apply(this,args)];
    })[0];
}

var result = piper(Math.min, Math.abs, Math.sqrt)(16, -9, 0)
// Output result:
console.log(result);

另外,像这样,fns数组中的第一个函数根本不会被调用。

.reduce通常,当累加器的类型与被迭代的数组中的项目的类型匹配匹配所需的结果类型时,您只会省略一个初始值,例如数字操作:

// sum:
const result = [1, 2, 3].reduce((a, b) => a + b);
console.log(result);

当然,如果数组有可能被迭代为空,您还应该提供一个初始值。

在(几乎?)所有其他情况下,提供初始值对于.reduce工作是必要的。


推荐阅读