React中的函数式编程及函数式编程定义的深刻解读
因为一直有了解函数式编程,也知道React是比较遵循函数式编程设计模式的框架,但是一直对函数是编程的定义和理解不是很清楚,到底函数式编程有上面优势,React如何遵循函数是编程,这些都是需要去仔细推敲的,可以让以后的代码写的更为优雅和合理
什么是函数式编程
函数是编程是一种设计思想,就像面向对象编程也是一种设计思想。函数式编程总的来说就是用尽量用函数组合来进行编程,先声明函数,然后调用函数的每一步都有返回值,将具体的每一步逻辑运算抽象,封装在函数中。再将函数组合来编写程序。
特性
函数是一等公民
这个特性的意思是函数可以和其他数据类型一样被赋给其他变量,作为参数,作为返回值。在js中函数具有这样特性,所有说js是支持函数式变成的,在js中的回调函数,闭包的实现就是利用了该特性。
用声明式,不用命令式
声明式就是声明一个函数,然后调用函数运算每部都有返回值,命令式就是直接运算
这里就以一个加法运算作为示例
#命令式
let i = 0
i += 1
i += 2
i += 3
#声明式
let i = 1
function add(val){
...
}
i.add(1)(2)(3)
这里的add
函数相当于一个黑盒,你不需要知道内部如何实现,你只需要知道add
的作用就是相加,而且可以多次不断复用
没有副作用的纯函数
首先我们需要理解什么叫纯函数,就是当同样的参数,传入函数后得到结果一样。那我们试想一下什么样的函数会输入同样的结果输出不一样呢。在函数内使用了外部的变量,因为外部的变量是会变化的,或者使用了外部变量,且在每次运行程序结束的时候改变了外部变量。所以函数式变成的另外两条规范就是:
- 函数内部不使用外部变量
- 函数内部不改变外部变量
通过这两点,就可以让函数完全与外部独立起来,不受外部影响,也不影响外部。这样函数调用就不会有各种因为外部环境变化产生的问题。
在这点上可以用slice
和splice
举个例子
//纯函数
let arr = [1,2,3]
console.log(arr.slice(0,1),arr)
[1] [1,2,3] //result
console.log(arr.slice(0,1),arr)
[1] [1,2,3] //result
//非纯函数
console.log(arr.splice(0,1),arr)
[1] [2,3] //result
console.log(arr.splice(0,1),arr)
[2] [3] //result
在这里我们可以联想到在js后来常用的一系列方法中,都保持了不修改原对象而返回一个新对象的规范如:reduce
,map
,find
,forEach
等等
同时ES6语法中更是推出了了一些新语法,帮助我们来创建返回一个新的对象,如扩展运算符[...arr]
可以简单的生成一个新的对象,同时解构可以方便的将对象中的值取出,并赋到一个新的对象上 ,与原来的对象脱离关系。可见js语法是趋向于函数式编程的
其他
函数式编程还具有函数柯里化-curry
,函数组合调用-cumpose
两个规范特性,这个在之后的博客中我会解释。
React的函数式编程
从函数式编程的特性,我们可以从很多方面想到React中具有的函数式编程的特征,
1.React的组件就是一个函数生成,React中的高阶组件就是函数中的高阶函数,如redux中的connect
和react-router
其实就是放在App外层的高阶函数。原理是相同的,就是将子组件传入父组件中,然后返回一个新的组件,可以复用夫父组件逻辑,这本身也是一种解耦。React页面的渲染过程本质就是函数的嵌套调用过程
2.React中子组件受父组件传入的props
控制,但是子组件不能直接修改props
,也就是单项数据流,这样就有点类似于纯函数的特性,不改变外部状态。所以我们在开发组件是,应当尽量将具有副作用的操作交给外部控制,这样的组件才是独立的,也具有高度的适应性。
3.在Redux
中这种函数是编程的思想更为明显,Reducer
命名来源就是来组员方法reduce
,两者都是将一些固定的运算抽象出来,每次都执行相同的任务。所以Reducer
内部必须是一个纯函数,而一些请求异步等具有副作用effect
的操作都交给中间件来完成。且每次调用完成都返回一个新的对象,不直接修改状态。这样的数据的操作更为清楚,你不需要考虑运行的结果因为其他的原因产生影响
4**.React和Redux中也使用了很多柯里话和函数组合调用的写法,例:**
//在redux中写一个中间件,使用了函数柯里化
const middleware = store => next => action => {
};
从上面这些点来看,react是有遵循函数式编程的特性地方,而redux是一个严格遵循函数式变成的插件
为什么要使用函数式编程
1.开发速度快,高度使用函数可以不断复用逻辑,函数对外为黑盒可直接无副作用的使用
2.通过函数名就可以直接理解用处,不需要了解内部实现,接近自然语言,相当于我们使用吹风机,不需要一步步制作吹风机。
3.代码更清晰,真正调用的代码很简单,所有细节逻辑都封装在函数内
4,方便并发处理,因为方法为纯函数不影响外部变量,可以随意排放处理顺序。
总结
综上所述函数式编程逐渐成为一种编程规范,也被大量的插件所遵循,所以我们在写代码的时候也应该尽量遵守这样的规范,这样有利于我们的代码更为合理,开发起来也更为高效,利于未来的拓展维护。