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

tutumiao tutumiao     2022-12-23     116

关键词:

最近正在学习阮一峰老师的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部分截图:

技术图片

二、管道机制(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中对于管道机制的一个示例,也可以帮助更好的理解管道机制的实现原理:

技术图片

读阮一峰老师es6入门笔记——第一章

  鉴于最近用vuejs框架开发项目,其中有很多涉及到es6语法不太理解所以便认真地读了一下这本书。  地址:http://es6.ruanyifeng.com/#README   第一章:let,const命令以及块级作用域  es6新增了let和const这两个变量的声明关... 查看详情

阮一峰老师的es6入门:async函数(代码片段)

async函数1.含义ES2017标准引入了async函数,使得异步操作变得更加方便。async函数是什么?一句话,它就是Generator函数的语法糖。前文有一个Generator函数,依次读取两个文件。constfs=require(‘fs‘);constreadFile=function(fileName)returnnewPromis... 查看详情

es6之let(理解闭包)和const命令

...之前很少接触,所以使用起来还不够熟悉。因此购买了阮一峰老师的ES6标准入门,在此感谢阮一峰老师的著作。  我们知道,ECMAScript6即ES6是ECMAScript的第五个版本,因为在2015年6月正式发布,所以又成为ECMAScript2015。ES6的主要... 查看详情

阮老师详解es6运算符扩展,浅显易懂!(代码片段)

大家好,我是漫步,之前我介绍过一篇关于ES6运算符的文章,今天分享阮一峰老师的一篇类似的文章,里面的分析和代码都很详细,希望对你有所帮助。目录指数运算符链判断运算符Null判断运算符逻辑赋值运... 查看详情

27理解js的继承机制(转载自阮一峰)

Javascript继承机制的设计思想 作者: 阮一峰日期: 2011年6月5日我一直很难理解Javascript语言的继承机制。它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instance)的区分,全靠一种很奇特的"原型链"(prototyp... 查看详情

es6(阮一峰)学习总结

在ES6之前,js只有全局作用域和函数作用域,ES6中let关键字为其引入了块级作用域。{vara=5;letb=6;}console.log(a);//5console.log(b);//bisundefinedlet声明的变量只能在其所在的代码块内才能访问,var声明的变量由于是全局变量,因此可以在代... 查看详情

阮一峰老师的javascript标准参考教程:object对象和object方法(代码片段)

Object对象1.概述1.1生成方法对象(object)是JavaScript语言的核心概念,也是最重要的数据类型。什么是对象?简单说,对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合。varobj=foo:‘Hello‘,bar:‘World‘;... 查看详情

flex布局(引用阮一峰老师的flex布局-语法篇)(代码片段)

一、Flex布局是什么?Flex是FlexibleBox的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为Flex布局。.boxdisplay:flex;行内元素也可以使用Flex布局。.boxdisplay:inline-flex;Webkit内核的浏览器,必须加上-w... 查看详情

《es6标准入门》(阮一峰)--17.iterator和for...of循环(代码片段)

1.Iterator(遍历器)的概念JavaScript原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6又添加了Map和Set。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是Map,Ma... 查看详情

es6学习之变量的解构赋值(代码片段)

...洁。事实上,只要是具有Iterator接口的都可以解构成功,关于iterable结构请关注我的博客,后续将会介绍,或者也可以去学习阮一峰老师的《ES6标准入门》的Iterator一章针对于更复杂的数组结构,也可以进行解析:let[a,[[b],c]]=[1,[ 查看详情

[jsonp]关于jsonp的几个点(代码片段)

关于JSONP今天学习到了JSONP,关于JSONP的定义和用法在阮一峰阮老师的博客里讲解得很清楚了,这里只是记录一些关于JSONP的点。回调函数的命名在阮老师的博客中举的例子是回调函数命名为foo,在实际使用环境中回调函数一般是... 查看详情

苹果是真牛逼

...话题。前几天我看到阮一峰老师发布的网络日志,是关于软件订阅制的话题。说句题外话,我个人非常喜欢看阮一峰老师的网络日志,也经常看他的博客,每周必看,因为阮一峰老师会聊一些非常有意思的话... 查看详情

深扒深入理解javascript中的生成器(代码片段)

...用,这一篇我们来深扒与迭代器息息相关的生成器。关于生成器有这样的描述红宝书:生成器是ES6新增的一个极为灵活的结构,拥有在一个函数块内暂停和恢复代码执行的能力阮一峰老师:Ge 查看详情

深扒深入理解javascript中的生成器(代码片段)

...用,这一篇我们来深扒与迭代器息息相关的生成器。关于生成器有这样的描述红宝书:生成器是ES6新增的一个极为灵活的结构,拥有在一个函数块内暂停和恢复代码执行的能力阮一峰老师:Ge 查看详情

理解oauth2.0-阮一峰的网络日志

...解OAuth2.0作者:阮一峰日期:2014年5月12日 OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。本文对OAuth2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC6749... 查看详情

阮一峰老师的javascript标准参考教程:数组array对象和array对象方法(代码片段)

数组1.定义数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示。vararr=[‘a‘,‘b‘,‘c‘];上面代码中的a、b、c就构成一个数组,两端的方括号是数组的标志。a是0号位置,b是1号位置... 查看详情

我对js异步执行机制的理解

...行机制,如果百度一下,你首先会发现阮一峰的写过一篇关于异步机制的文章(http://www.ruanyifeng.com/blog/2014/10/event-loop.html),等你津津有味又一头雾水的看完,然后继续看百度的其他结果,然后会发现,阮一峰的这篇被另一个大... 查看详情

es6阮一峰阅读学习

参考:ECMAScript6入门 一、ECMAScript6简介1.什么是ECMAScript6? JavaScript语言的下一代标准。2015年6月发布,正式名称是《ECMAScript2015标准》。思考:编程语言和英语、法语语言差不多吧。其实就是语言的标准、规范之类,和英... 查看详情