请选择 进入手机版 | 继续访问电脑版
查看: 184|回复: 1

关于阮一峰老师es6(第三版)中管道机制代码的理解浅析

[复制链接]
  • TA的每日心情
    开心
    8 小时前
  • 签到天数: 1574 天

    [LV.Master]伴坛终老

    4248

    主题

    6170

    帖子

    10万

    积分

    管理员

    IBC编程社区-原道楠

    Rank: 9Rank: 9Rank: 9

    积分
    108845

    推广达人突出贡献优秀版主荣誉管理论坛元老

    发表于 2019-10-24 09:50:57 | 显示全部楼层 |阅读模式

    马上加入IBC,查看更多教程

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    近来正在学习阮一峰老师的es6(第三版)讲义,在学到第七章《函数的扩展》中的箭头函数嵌套时,文中提到了一个关于“管道机制”的示例,文中源代码如下:
    //es6(第三版)讲义中的管道机制源代码:
    const pipeline = (...funcs) =>
    val => funcs.reduce((a, b) => b(a), val);
    const plus1 = a => a + 1;
    const mult2 = a => a * 2;
    const addThenMult = pipeline(plus1, mult2);
    addThenMult(5);
    下面为我对这段代码的明白分析:
    一、这段代码中用到了2个主要知识点:
    1、es6中的新特性:rest参数(即上面代码中pipeline函数的形参…funcs,它表示pipeline函数的形参是一个包罗多个函数的函数数组,funcs则为数组名),形式为:…变量名。用于获取函数的多个参数,类似于之前的arguments对象。rest参数搭配的变量是一个数组,该变量可以将多个参数放入此中。因为rest参数中的变量代表一个数组,所以数组特有的方法都可以用于这个变量。
    2、数组对象的reduce()方法(这也是实现管道机制的核心技能):
    reduce() 方法汲取一个函数作为回调函数,reduce()方法为数组中的每一个元素(从左到右)依次实行这个回调函数,终极计算为一个值。
    语法:arrayObject.reduce(function(prev, currentItem, currentIndex, arrayObject), initialValue)
    参数:
    ●prev:必需。表示数组中前一个元素调用reduce() 方法回调函数后的返回值,或者初始值 initialValue;
    ●currentItem:必需。表示当前正在调用reduce() 方法回调函数的数组元素;
    ●currentIndex:可选。表示当前正在调用reduce() 方法回调函数的数组元素的索引。若提供了 initialValue值,则索引为0,否则索引为1;
    ●arrayObject:可选。当前正在调用reduce() 方法回调函数元素所属的数组对象(即调用reduce()的数组);
    ●initialValue:可选。通报给此reduce() 方法回调函数的初始值。作为第一次调用回调函数时的第一个参数的值。 假如没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。
    关于initialValue参数作用的进一步分析:回调函数第一次实行时,prev 和currentItem的取值有两种环境:假如调用reduce()时提供了initialValue,则prev取值为initialValue,currentItem取数组中的第一个元素;假如没有提供 initialValue,那么prev取数组中的第一个元素,currentItem取数组中的第二个元素。假如没有提供initialValue,reduce 会从索引1的数组元素开始实行回调函数,跳过第0个索引。假如提供initialValue,则从索引0开始。假如数组为空且没有提供initialValue,会抛出TypeError 。假如数组仅有一个元素,而且没有提供initialValue, 或者有提供initialValue但是数组为空,那么此唯一值将被返回而且回调函数不会被实行。
    关于reduce()方法的运用实例,可以参照MDN这篇文章:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce,会更有利于资助明白这个方法的用途。以下为MDN部门截图:
    095057woco8lx2thacohva.jpg


    二、管道机制(pipeline):(MDN中也称“功能型函数管道”)即前一个函数的输出是后一个函数的输入。管道机制类似于jQuery中的链式编程,以return的形式持续操作。
    三、这段代码实现的功能为:让一个数字先与1相加,得出的结果然后再与2相乘,最后返回计算后的结果。
    四、经过对上面代码的一番思索,我根据本身的明白将上面代码的参数表示稍作了一点语义化的改动,让我更清楚的明白这段代码的运行机制:
    const pipeline = (...funcs) =>
    num => {
    console.log( num);
    return funcs.reduce((prev, fn) => fn(prev), num);
    }
    const plus1 = num=> num + 1;
    const mult2 = num => num * 2;
    const addThenMult = pipeline(plus1, mult2);
    console.log(addThenMult(5)) ; //12
    下面为这段代码的详细解释详解:
    const pipeline = (...funcs) =>
    num => {
    //打印这个形参 num看一下, num就是通报给reduce方法里回调函数的初始值
    console.log( num);
    //funcs数组调用reduce()方法,这时,初始值num就是reduce回调函数中的第一个形参prev,而此时reduce回调函数中的第二个形参fn则代表funcs数组里的第一个函数。根据这个回调函数的函数体:(prev, fn) => fn(prev)实行,起首将初始值num(即prev)通报给funcs数组里的第一个函数(即fn())作为实参并举行第一个函数的调用,第一个函数的运算结果得出后紧接着把这个结果再传给funcs数组里第二个函数作为第二个函数的实参并举行调用,第二个函数的运算结果得出后紧接着再传给第三个函数作为第三个函数的实参并举行调用,以此类推。。。。。。直到funcs数组中的最后一个函数元素实行完毕后,pipeline函数返回的函数的返回值就是reduce()方法的返回值,而reduce()方法的返回值就是funcs数组中最后一个函数参数实行回调函数后返回的值。
    return funcs.reduce((prev, fn) => fn(prev), num);
    }
    const plus1 = num => num + 1;
    const mult2 = num => num * 2;
    //实参plus1函数对应形参funcs数组中的第一项元素,也就是pipeline函数的第一个形参
    //实参mult2函数对应形参funcs数组中的第二项元素,也就是pipeline函数的第二个形参
    const addThenMult = pipeline(plus1, mult2);
    //这里的实参“5”就是通报给pipeline()函数return回的addThenMult函数中funcs数组调用reduce()方法后的回调函数的初始值 num。 5会先作为plus1函数的实参传入并实行plus1函数,结果为5+1=6;然后再将这个结果6通报给mult2函数作为mult2函数的实参并实行mult2函数,结果为6*2=12。
    console.log(addThenMult(5))
    //所以最后devtools中上面两处console.log()打印出的结果分别为:
    >>5
    >>12
    五、最后,再附上一张MDN中对于管道机制的一个示例,也可以资助更好的明白管道机制的实现原理:
    095058ivaqjyy5jzv1g59b.jpg








    来源:https://www.cnblogs.com/tutumiao/archive/2019/10/23/11725661.html
    C#论坛 www.ibcibc.com IBC编程社区
    C#
    C#论坛
    IBC编程社区
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则