引导阅读 =>《js函数式编程指南》
ES6函数式编程博客 => https://www.cnblogs.com/wangking/p/11168629.html
阮一峰函数式编程入门教程 => http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html
编程本质
编程的本质其实就是,操纵一坨数据。
当然操纵的方式有许多,存储的方式也五花八门,但是本质不变,就是访问数据(读取以及改变)。
数据存放方式来区分
1、面向对象编程 —— Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
对于OOP(面向对象,下同),数据存放在对象的属性(成员变量)里面,以及静态成员(全局变量)。
2、函数式编程(请注意多了一个“式”字) —— Functional Programming,简称FP,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算。
对于FP(函数式,下同),数据存放在闭包(各级作用域)里面,作用域包括全局作用域。
数据访问方式
数据存放方式决定了访问的方式。
1、对于OOP来说,访问数据(全局变量除外)需要先获取对象的引用,然后再进行操作(直接访问——公共属性,或者调用成员函数/方法访问——私有属性)
2、对于FP,访问数据是直接访问(通过函数入参或者作用域链查找)
编程方式
从中我们可以看出一些东西,OOP是通过持有,以及传递对象的方式去让别的对象来操作数据,而对象也会是其他对象的成员,层层嵌套。当你想要访问某一个数据的时候,就需要顺着对象的引用链条去找,一步步去操作。
FP传递的则是函数,调用函数即操作数据,传递函数的时候其实隐含着传递了函数创建的时候所附带的作用域,这个在表面上看不出来,在底层是有的。
本质区别
换句话说OOP,是面向作用域编程(也就是存在作用域this)。而FP,是面向功能编程。
FP有一个巨大的优势,就是作用域链,也就是说函数可以访问的变量范围要远远大于OOP,灵活性就成几何级数上升,说到FP必定少不了高阶函数。
js是一门面对对象的语言,不是一种纯函数语言,更像是一种多范式语言,但是非常适合函数式编程。
高阶函数
定义:JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
高阶函数(HOC):
- 接收函数作为参数(参数是函数)
- 返回函数作为输出(返回值是函数)
- 接收函数作为参数且返回函数作为输出(以上两种都存在)
满足以上(三个条件中的一个就行)的函数就是高阶函数。
常见的高阶函数有 map,forEach,every,some,sort... 等等。
高阶函数与闭包
闭包有3个可以访问的作用域:
1.闭包函数内声明的变量
2.对全局变量的访问
3.对外部函数变量的访问
柯里化函数
言归正传,什么是函数柯里化?函数柯里化(curry)就是只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。听得很绕口,其实很简单,其实就是将函数的变量拆分开来调用:f(x,y,z) -> f(x)(y)(z)
。
函数组合和柯里化(compose)
将传入的函数变成两个,通过组合的方式返回一个新的函数,让代码从右向左运行,而不是从内向外运行。
函数组合和柯里化有一个好处就是pointfree。
pointfree 模式指的是,永远不必说出你的数据。它的意思是说,函数无须提及将要操作的数据是什么样的。一等公民的函数、柯里化(curry)以及组合协作起来非常有助于实现这种模式。
不使用所要处理的值,只合成运算过程。中文可以译作"无值"风格。我们完全可以把数据处理的过程,定义成一种与参数无关的合成运算。不需要用到代表数据的那个参数,只要把一些简单的运算步骤合成在一起即可。
函数式编程有什么优势呢?我现在觉得,pointfree 就是如何使用函数式编程的答案。
偏函数
减少参数封锁部分参数