函数式编程
函数式编程是一种编程范式。与常见的面向对象编程、面向过程编程是并列的关系。
函数式编程的思维方式是将现实世界中的事物和事物之间的联系抽象到程序世界。是对运算过程进行抽象。
函数式编程中的函数不是程序中的函数(方法),而是数学中的函数。即映射关系
函数式编程中的函数的相同的输入始终得到相同的输出(纯函数)
高阶函数是函数式编程的一个特性。
函数是一等公民
根据维基百科,编程语言中一等公民的概念是由英国计算机学家Christopher Strachey提出来的,时间则早在上个世纪 60 年代,那个时候还没有个人电脑,没有互联网,没有浏览器,也没有 JavaScript。 他也只是提出了一等公民的概念,没有给出严格的定义。
关于一等公民,我找到一个权威的定义,来自于一本书《Programming Language Pragmatics》,这本书是很多大学的程序语言设计的教材。
In general, a value in a programming language is said to have first-class status if it can be passed as a parameter, returned from a subroutine, or assigned into a variable.
也就是说,在编程语言中,一等公民可以作为函数参数,可以作为函数返回值,也可以赋值给变量。
JavaScript中函数就是一个普通对象,可以通过new Function的方式创建一个函数对象。因此它可以赋值给变量,也可以作为函数的参数,还可以作为函数的返回值,因此JavaScript中函数是一等公民
高阶函数
高阶函数肯定是一个函数,不同的是输入的参数和返回的值,这两项中的一项必须是函数才能叫高阶函数
使用高阶函数的意义
高阶函数用来抽象通用的问题,抽象可以帮我们屏蔽细节,只需要关注我们的目标
常用的高阶函数
forEach | filter | every| some | map
闭包
闭包是指可以在另一个作用域中调用一个函数的内部函数并访问到该函数作用域中的成员
闭包的本质
函数在执行的时候会放到一个执行栈上,当函数执行完毕之后会从执行栈上移除,但是堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问到外部函数成员
使用闭包的优缺点
闭包的优点:
- 可以让一个变量长期存储在内存中
- 可以避免全局变量的污染
- 封装对象的私有属性和私有方法,然后在全局作用域中通过调用闭包就能访问函数中的变量
闭包的缺点
- 变量长期存储在内存中,会增加内存的使用量
- 使用不当会造成内存泄露
通过let定义的变量的作用域通过script查到;通过var定义的变量会被挂载到全局对象 scope作用域
纯函数
纯函数是指相同的输入始终得到相同的输出,而且没有任何可观察的副作用
纯函数的好处
- 可缓存(可以借助lodash的memoize方法,将纯函数作为参数传入)
- 可测试(因为纯函数始终有输入和输出)
- 方便并行处理(在多线程环境下并行操作共享的数据很可能出现意外情况,而纯函数不需要访问共享的内存数据,因此可以进行并行处理)
lodash
lodash是一个JavaScript的工具库,内部封装了很多对字符串、数组、对象等常见数据类型的处理函数。可以通过npm install lodash命令安装。
lodash的所有函数都不会在原有的数据上进行操作,而是复制出来一个新的数据而不改变原有数据
-
lodash中的柯里化函数——curry() curry的功能:创建一个函数,该函数接收一个或多个需要柯里化的函数func作为参数,如果func所需要的参数都被提供则执行func并返回执行的结果;否则继续返回该函数并等待接收剩余的参数
-
lodash中的组合函数——flow()或者flowRight() flow是从左往右运行;flowRight是从右往左运行,使用的更多一些
-
lodash中的fp模块——fp模块提供了已经被柯里化的函数。fp模块的函数遵循函数优先,数据滞后的原则
函数组合可以让我们把细粒度的函数重新组合生成一个新的函数。
副作用
副作用是让函数变得不纯。如果函数依赖于外部的状态就无法保证始终得到相同的输出,就会带来副作用
所有的外部交互都有可能带来副作用,副作用也使得方法的通用性下降,不适合扩展和可重用性,同时副作用会给程序中带来安全隐患,给程序带来不确定性,但是副作用不能完全禁止,尽可能控制它们在可控范围内
柯里化
柯里化是指一个函数有多个参数时,可以对函数进行改造,调用这个函数只传递部分参数(这部分参数以后永远不变),并且让这个函数返回一个新的函数,新的函数去接收剩余的参数,并返回结果。
柯里化让函数变得更灵活,让函数的粒度更小;可以把多元函数转换为一元函数,可以组合使用函数产生更强大的功能
函数组合
函数组合(compose):如果一个函数要经过多个函数处理才能得到最终值,这个时候就可以把中间过程的函数合并成一个函数。函数就像是数据的管道,函数组合就是把这些管道连接起来,让数据穿过多个管道形成最终结果。
函数组合默认是从右往左执行
函数组合要满足结合律。
结合律是指三个函数组合时,既可以先组合前两个函数,又可以先组合后两个函数