问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

javascript函数式编程基础

发布网友 发布时间:2024-09-25 18:59

我来回答

1个回答

热心网友 时间:2024-12-02 18:31

函数式编程概念

程序的本质是根据输入得到输出。x->f(联系、映射)->y,y=f(x)。

函数是一等公民,就是一个普通的对象。它能作为另一个函数的参数,也能作为一个函数的返回值,还可以当作变量存储

//非函数constnum1=2;constnum2=3;constsum=num1+num2;//console.log(sum)//函数式(函数表达式,将函数作为一个变量赋值)constadd=(num1,num2)=>{returnnum1+num2;}//console.log(add(num1,num2))高阶函数

高阶函数可以让我们用来公用通用的方法(forEach,map,rece,some,every,find,findIndex)

满足高阶函数的条件必须达到其中之一:

1.一个函数的参数可以是另一个函数2.函数的返回值为另一个函数//函数作为参数,如下forEach,filter//手写forEach函数constforEach=(array,fun)=>{for(letindex=0;index<array.length;index++){constelement=array[index];fun(element)}}forEach([1,2,3,4,5],num=>console.log(num*2))//246810//手写filter函数constfilter=(array,fun)=>{constresult=[];for(letindex=0;index<array.length;index++){constelement=array[index];if(fun(element))result.push(element)}returnresult;}console.log(filter([1,2,3,4,5],num=>num%2===0))//[2,4]//函数作为返回值,如makeFn,onceconstmakeFn=()=>{constmsg='hellofunction';return_=>console.log(msg);}makeFn()()//hellofunction//只会付一次钱constonce=fn=>{letdone=false;returnfunction(){if(!done){done=true;fn.apply(this,arguments)}}}constpay=once((money)=>{console.log(`支付${money}元钱`)})pay(5)pay(5)pay(5)支付5元钱闭包函数

以在另一个作用域中调用一个函数的内部函数并访问到该函数的作用域中的成员(外部访问一个函数的内部函数,这个内部函数引用了函数的成员)

闭包的本质:函数在执行的时候会放到一个执行栈上当函数执行完毕之后会从执行栈上移除,但是堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问外部函数的成员

上面的makeFn、once都用到了闭包,闭包必然是一个高阶函数,因为把函数作为了返回值

/*例如求一个数的n次方,如果我有大量的值需要求2次方,则我们可以先生成一个2次方的函数,接着传所需的值。这里,外层函数的参数power在makePower执行完毕后,并没有被销毁,内部函数还要继续使用,所以就形成了闭包*/constmakePower=(power)=>num=>Math.pow(num,power);constpower2=makePower(2);constpower3=makePower(3);console.log(power2(3))console.log(power3(3))纯函数

相同的输入永远会得到相同的输出,而且没有任何可观察的副作用(意思就是外部的状态),纯函数就类似数学中的函数(用来描述输入和输出之间的关系),y=f(x)

//不纯函数,mini是一个外部的配置属性,如果改变了,则不满足纯函数的条件constmini=18;constcheckAge=age=>age>mini;//修改成纯函数constcheckAge=age=>{constmini=18;returnage>age;}副作用

副作用会让你个函数变得不纯,副作用不可能完全禁止,尽可能控制他们在可控范围内发生,如上述纯函数的例子。

副作用的来源:1.配置文件2.数据库3.用户的输入......

柯里化

当一个函数有多个参数的时候,这时候可以先传递一部分参数调用,然后返回一个新的函数接受剩余的参数,直到参数接受完毕,返回结果

相当于对一个多参数的函数分批次执行,我们可以得到其中的函数缓存

特点:1.柯里化可以让我们给函数传递较少的参数得到一个已经记住了某些固定参数的新函数2.这是一种对函数参数的缓存3.让函数变得更灵活,让函数得颗粒度更小4.可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能

//柯里化检查年龄函数constcheckAge=mini=>age=>age>mini;constcheck18=checkAge2(18);console.log(check18(20));//true/*自己实现柯里化,首先参数是一个函数,这个函数的参数有N个,且返回值也是一个函数,当这个函数被柯里化后,调用这个函数,如果参数小于N个,则继续返回一个函数,等待剩余参数得传递,如果参数等于N个了,则直接返回最终结果*/constcurry=fn=>{returnfunctioncurriedFn(...args){//判断实参跟形参的个数if(args.length<fn.length){returnfunction(){returncurriedFn(...args,...arguments);}}returnfn(...args);}}constownerCurriedFilter=curry((fn,array)=>array.filter(fn))//两种方式得到的结果一样console.log(ownerCurriedFilter(num=>num%2===0,[1,2,3,4]))console.log(ownerCurriedFilter(num=>num%2===0)([1,2,3,4]))//[2,4]函数组合

如果一个函数要经过多个函数处理才能得到最终值,这个时候可以把中间过程的函数合并成一个函数

特点:1.函数就像是数据的管道,函数组合就是把这些管道连接起来,让数据穿过多个管道形成最终结果2.函数组合默认从右到左执行3.函数组合满足结合律

constreverse=array=>array.reverse();constfirst=array=>array[0];consttoUpper=str=>str.toUpperCase();//这里用到了lodash库constflowRightFn=_.flowRight(toUpper,first,reverse);console.log(flowRightFn(['aaa','bbb','ccc']));//CCC/*实现函数组合,首先传递的参数是一组函数,返回的是一个函数,特点就是上一个函数执行的返回值是下一个函数的参数,类似管道形式往下传递,直到所有函数运行完返回结果*/constcompose=(...args)=>{returnfunction(value){returnargs.reverse().rece((current,fn)=>{returnfn(current)},value)}}constflowRightFn=compose(toUpper,first,reverse);console.log(flowRightFn1(['aaa','bbb','ccc']));//CCC

lodash是一个非常实用的函数库,对字符串、数组、对象的处理等函数都是纯函数,其中的fp模块中的函数都是被柯里化的,可以直接用。熟练使用lodash库可以提升开发效率

pointfree模式是一种编程风格,就是函数的组合

特点:1.不需要指明处理的数据2.只需要合成运算的过程3.需要定义一些辅助的基本运算函数

Funtor函子

目的是在函数式编程中如何把副作用控制在可控范围内,异常处理,异步操作等。个人理解就是一个盒子,这个盒子里存放了一个值,这个值对外是不可见,要获取这个值,或者操作这个值都需要特定执行才能拿到,且处理完这个值之后则继续返回一个盒子,这个盒子里装的是你新的值。

特点:1.函数式编程的运算不直接操作值,而是由函子完成2.函子就是实现;map契约的对象3.我们可以把函子想象成一个盒子,盒子里封装了一个值4.想要处理盒子中的值,我们需要给盒子的map防滑传递一个处理值的纯函数,有这个函数来对值进行处理5.最终map方法返回一个包含新值的函子

//一个最基本的函子,一个容器,包裹一个值classContainer{//of静态方法,可以省略new关键字创建对象staticof(value){returnnewContainer(value)}constructor(value){this._value=value}//map方法,传入函数,将容器里的每一个值映射到另一个容器map(fn){returnContainer.of(fn(this._value));}}Container.of(2).map(x=>x+2).map(x=>x*x)IO函子

特点:1.IO函子中的_.value是一个函数,这里把函数作为值来处理2.IO函子可以把不纯的动作储存到_value中,延迟执行这个不存的操作,保证当前的操作纯3.把不存的操作交给调用者来处理

1.一个函数的参数可以是另一个函数2.函数的返回值为另一个函数0
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
八个月孕妇痔疮怎么办 怀孕痔疮严重怎么缓解 孕妇能割痔疮吗 孕37周痔疮严重怎么办 孕37周痔疮可以顺产吗 怀孕晚期痔疮严重怎么办 我打开网上邻居,里面变成空的了,以前打开就有“宽带连接”和“本地连 ... 单位有些电脑打开网上邻居没东西显示是为什么? 生产线称重 梦比优斯奥特曼第35集19:38秒时,希卡利站起来时的那个背景音乐是... 梦比优斯奥特曼中希卡利出现时的音乐 手机之间怎么传软件? 古籍版本知识500问图书目录 酒店客房部的人数量及岗位情况 Excel表格做得好的帮我改下这个表格,能否把分页整成一个页? 无抵押银行贷款50万一年利息多少钱 为什么抖音不能更改昵称呢? 为什么我不能更改系统属性文件夹? 怎么把vivo账号的联系人导入另外一个手机 为什么编辑cad颜色不能更改? 电脑为什么不能修改时间? 手机上有一个广告病毒,无法卸载,它还能控制杀毒软件闪退特别厉害 电脑桌面图片为什么改不了啊? qq浏览器免费看起点Vip,现在取消了吗? 我怎么也没看到"畅想读书月" 黑龙江省哈尔滨市身份证号码开头 开化是哪个市的 浙江省衢州市开化县的电话区号是什么? 为什么我的Mac地址一直不能改? 为什么我的苹果id不能用? excel分页如何分别设置重复标题行excel如何在分页显示时重复表头行 为什么我的微信手机号绑定不能修改了呢? javascript如何实现一个可配置的自定义函数?有提问例子 excel表格如何设置分页符excel表格分页符怎么用 借款合同复印件是否有效 借款合同丢失复印件能作为打官司时的证据吗 社会保险基金管理当前社会保险基金管理中存在的主要问题 社会保险基金管理中存在的主要问题都有哪些? 我刚学打篮球,不怎么会打。想请教高手一些基本问题,有愿意的留个QQ... 20岁男生想学打篮球,但是一点也不懂,请高手详细指点,谢谢! 请教:关于社会保险的几个问题--北京 今年高一,身高180,体重60。想打篮球,我只是菜鸟,不会运球,弹跳力不高... Word中如何更改图表类型和添加数据标签word中如何更改图表类型和添加... 农机安全监理人员管理规范发文通知 农机安全监理机构建设规范农业部通知 农机安全监理机构建设规范农机安全监理机构建设规范 小学二年级数学表内乘法:3x4二4x5一()括号里该填什么数? 5x5=25的口诀? 福建省农业机械管理条例第四章 安全监理 5➕5➕5➕5改成乘法算式是4✖️5还是5✖️4? 徐州市农业机械安全监督管理条例第四章 安全监督检查 别人的微信号被封了,还能发信息吗?