函数式编程是一个新奇难懂的模型,虽然现在已经被我们普遍使用了,但是我们可以查资料学习学习的原理范畴论1、范畴论范畴论函数式编程是范畴论数学的一个分支是复杂的数学。范畴轮认为世界上所有的概念系统都可以抽象成范畴。范畴范畴认为万物、物、物之间都存在一定的关系,任何事物都可以找到关系。可以定位为一个范畴的单线箭头,表示范畴成员之间的关系,称为“态射”。同一范畴的所有成员都是不同状态的变换,通过态射变换2.函数式编程编程中的所有成员都是一个集合,变换关系是一个函数。函数式程序设计的基本模型最初是用来计算λ(lambdax=>x*2)的微积分,不是在计算机上设计的,后来被引用来研究函数定义、函数应用和递归的形式化系统。函数式编程不是用函数式编程,也不是传统的面向过程的编程。主要思想是将复杂的功能拆分为简单的简单功能。计算过程是一系列嵌套的函数调用。JavaScript是披着C外衣的lisp函数式编程。随着react的高级功能的发展,逐渐被开发者所使用,进而形成了一种开发模式。Vue3也采用了这种模式3,javascript函数式编程的思想,和其他数据类型一样,函数可以赋值给其他变量,作为参数传递,作为其他函数返回。函数在编程时用作参数,不能修改。作为变量,只能赋值一次,没有任何“副作用”map&&redux是最常用的函数式编程方式没有语句,没有while,改用递归,if-else可以用三元运算符代替引用透明(函数只运行在parameters)4.纯函数函数不依赖外部变量产生运行结果。同一个输入得到的输出永远是一样的,原始数据的值不会改变。slice和splice的区别在于前者是纯的,后者是不纯的。特点:可缓存,同样的操作第一次运行速度慢,后面的程序运行速度很快。比如lodash的memorize函数可以记录一个函数的计算过程。计算过程链很长,可以多级处理。函数添加(x,y){this.val=x+y;}letstr=add.bind(null,"str");//防止this随机指向,绑定一个nulllets=newstr("ing");s.val//string//使用lodash的curry函数letmatch=curry((reg,str)=>str.match(reg));letfilter=curry((f,arr)=>arr.filter(f));让hasSpace=匹配(/\s+/g);letarr=["abcd","acbd"]filter(hasSpace)(arr);6,函数组成:洋葱模型h(g(f(x)))咖喱变换,积木constcompose=(g,f)=>x=>g(f(x));让第一个=arr=>arr[0];让reverse=arr=>arr.reverse();letlast=compose(first,reverse);last([1,2,3,4]);7.PointFree将对象自带的方法转换为纯函数,不要转瞬即逝中间变量constf=str=>str.toUpperCase().split("");//转换:lettoUpperCase=word=>word.toUpperCase();letsplit=x=>(str.split(x));letf=compose(split(''),toUpperCase);f("abcd");8.声明式和命令式代码声明式:函数式编程的使用letbooks=bookShop.map(s=>s.book);imperative:letbooks=[];for(leti=0,;i高密度、低耦合10.使用高阶函数作为参数11.尾部调整优化最后函数中的step是函数调用,调用的返回值直接给函数;如果函数本身就是尾递归函数递归需要保存大量调用记录,栈溢出错误次数大,尾递归优化,递归进入循环,只需要保存一条调用记录,不会出现栈溢出错误注意:ES6强制使用尾递归优化函数f(n){如果(n==1){返回1;}returnn*f(n-1);}//非尾递归,函数f(n,t)中有参数参与{if(n==1){returnt;}returnf(n-1,n*t);}//尾递归,只保留一条调用记录尾递归:函数最后一步调用自己,不是最后一行,调用其他函数称为tailcallTailrecursion当前问题:现代浏览器并不完全支持,只更新当前栈内存信息。执行引擎消除了递归。开发者不知道堆栈执行信息丢失,调试困难。12.闭包函数域栈调用帧释放,函数内部变量堆内存保存,然后外部使用return回调函数,可以访问私有变量到functionp(x){functiong(y){返回Math.pow(y,x);}返回g;}varsquare=f(2);square(3);//9Container,Functor概念:容器包含值与值之间的映射关系映射关系是函数function的操作方法=>函数式编程数理逻辑、微积分、行列式等计算方法,纯函数,仅用于评估,无需业务参与,可以满足功能算法。一个容器通过函数操作映射对另一个容器进行编程。Functor就是利用了这两个容器之间的映射关系。Functor用作将数据值加载到容器中的函数。,保留map出口,让其他函数调用通过映射关系得到的新值//ES5varFunctor=function(x){this.__value=x;}Functor.of=x=>newFunctor(x);Functor.prototype.map=function(f){returnFunctor.of(f(this.__value));}Functor.of(3).map(x=>x+1).map(x=>'elel'+x);//ES6类Functor{constructor(val){this.val=val}map(f){returnnewFunctor(f(this.val));}}1.可能函数式编程没有try,catch和if,else,所以处理外部传入的null值和判断需要一个Functor操作(三元判断)Functor.of(null).map(function(s){returns.toUpperCase();});//ES6classMaybeextendsFunctor{isNothing(){return(this.val===null||this.val===undefined);}map(f){返回this.isNothing()?Maybe.of(null):Maybe.of(f(this.val));}}Maybe.of(null).map(function(s){returns.toUpperCase();});//ES5varMaybe=function(s){this._value=s;}Maybe.of=function(s){returnnewMaybe(s);}Maybe.prototype.map=function(f){returnthis.isNothing?Maybe.of(null):Maybe.of(f(this._value));}Maybe.prototype.isNothing=function(){return(this._value===null||this._value===undefined);}2.错误处理,Either,AP容器需要处理一些特殊情况,promise可以调用catch处理Error,either表示or的逻辑操作:将if··else替换为函数式中的try···catch,以及分为左值和右值,通常右值生效,如果右值不存在,则左值作为默认值类生效extendsFunctor{constructor(left,right){this.left=left;this.right=正确;}map(f){this.right?Either.of(this.left,f(this.right)):Either.of(f(this.left),this.right);}}Either.of=function(left,right){returnnewEither(left,right);}classLeftextendsFunctor{constructor(x){this._value=x;}map(f){返回这个;}}classRightextendsFunctor{constructor(x){this._value=x;}map(f){returnRight.of(f(this._value));}}3.IOlazyevaluation将非纯函数的操作或数据(http,DOM)包装起来,交给外部运行环境处理。它的__value是一个函数Monad:一种设计模式。例如promise函数的输入输出是一种数据类型,是一种将一种数据转换成另一种数据的装箱过程。取出两个容器的值,运行完成后生成一个新的容器抛出给其他用户使用。流程是数据类型之间的操作,黑盒流程classFunctor{constructor(val){this.__value=val}map(f){returnnewFunctor(f(this.__value));}}classMonadextendsFunctor{join(){returnthis.__value;}flatMap(f){返回这个。地图(f)。加入();}}类IO扩展Monad{map(f){返回IO。的(撰写(f,这个。__value));}}letreadFile=function(filename){returnnewIO(function(){returnfs.readFileSync(filename,'utf-8');});}readFile('./user.txt').flatMap(tail).flatMap(print);