概要:函数式编程和面向对象是日常编程中非常常见的。在前端项目的开发中,经常是面向对象与函数式编程混合使用,本文进行案例函数式与面向对象的一些对比。然后从hook的角度引入函数式组件再到vue3的函数式编程。也有部分java的lambda与stream流的函数式编程。
1、对于OO来说,访问数据(全局变量除外)需要先获取对象的引用,然后再进行操作(直接访问——公共属性,或者调用成员函数/方法访问——私有属性)
2、对于函数式,访问数据是直接访问(通过函数入参或者作用域链查找)
//OO
class Foo {
constructor(){
this.bar = 0
}
}
let foo = new Foo()
foo.bar ++
//函数式
let bar = 0
function foo(){
bar ++
}
foo()
从代码上可以看出,函数式编程更加的简洁。函数式编程调用数据的时候不需要先new 出对象再去考虑操作,而是以着函数优先的角度去考虑问题。
在函数式编程中。所有的数据都是不可变的,不同的函数之间通过数据流来交换信息,函数作为一等公民,享有跟数据一样的地位,可以作为参数传递给下一个函数,同时也可以作为返回值。
2.1 所有的数据都是不可变的,所以所有的变量在程序运行期间都是一直存在的,非常占用运行资源
2.2 函数式编程在大规模工程如果对函数式编程的理解不够深刻就会出现晦涩难懂的局面。
2.3 函数式写法更加灵活,更加符合语义。
2.4.在函数式编程中,编程的主要重点是我们在做什么。在面向对象的编程中,编程的主要重点是我们如何做。
react官网案例 useState
import React, { useState } from 'react';
function Example() {
// 声明一个新的叫做 “count” 的 state 变量
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
总结
1.function component 将会是接下来各大框架发展的一个方向,function天然对TS的友好也是一个重要的影响;
2.react hook的上手成本相对于vue会难一些,vue天生规避了一些react中比较难处理的地方;
3.hook一定是大前端的一个趋势
这部分借鉴:https://blog.csdn.net/weixin_33929309/article/details/93164243
vue2是将mounted,data,computed,watch之类的方法作为一个对象的属性进行导出。
vue3新增了一个名为setup的入口函数,value, computed, watch, onMounted等方法都需要从外部import。
在vue3中,我们可以像写一个方法一样去写这个组件的JS逻辑部分,使用import来按需引入。这样的好处显而易见,首先就是我们需要写的代码量少了,其次就是我们可以封装更多的子函数、引用更多的公共函数去维护我们的代码,第三就是代码的可读性变高了。(当然,我们的打包体积也会变小)
vue2的代码组织结构
<script>
import ueditor from 'ueditor'
export default {
data () {
return {
ue: null,
ueId: `J_ueditorBox_${new Date().getTime()}`,
ueContent: '',
dialogVisible: false
}
},
mounted () {
this.ue = ueditor.getEditor(this.ueId, {
// serverUrl: '', // 服务器统一请求接口路径
zIndex: 3000
})
},
methods: {
getContent () {
this.dialogVisible = true
this.ue.ready(() => {
this.ueContent = this.ue.getContent()
})
}
}
}
</script>
vue3的函数式编程
<script>
import { value, computed, watch, onMounted } from 'vue'
export default {
setup() {
// reactive state
const count = value(0)
// computed state
const plusOne = computed(() => count.value + 1)
// method
const increment = () => { count.value++ }
// watch
watch(() => count.value * 2, val => {
console.log(`count * 2 is ${val}`)
})
// lifecycle
onMounted(() => {
console.log(`mounted`)
})
// expose bindings on render context
return {
count,
plusOne,
increment
}
}
}
</script>
java项目中的函数式编程的使用感觉和前端项目中是很不一样的。java中使用函数式编程可以极大的减轻代码量,但是归根结构还是在为对象的某些属性或者方法服务。
4.1 下面简单的以线程的这个简单的经典案例举例子。借用lambda表达式,省略了new Runnable()的过程,并且直接重写父类的run方法,不需要@Override
public static void main(String[] args) {
// Java7
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}
}).start();
// Java8
new Thread(() -> {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}).start();
}
4.2 也应用比较多的场景有stream流数据的转换
// 2.查询所有属性
List<AttrGroupEntity> attrGroupEntities = this.getData();
List<AttrGroupWithAttrsVo> collect = attrGroupEntities.stream().map((item) -> {
// 对原有对象 AttrGroupEntity 处理封装出新的对象 AttrGroupWithAttrsVo
AttrGroupWithAttrsVo attrGroupWithAttrsVo = new AttrGroupWithAttrsVo();
BeanUtils.copyProperties(item,attrGroupWithAttrsVo);
// 查询出属性分组的id然后赋值
List<AttrEntity> relationAttr = attrService.getRelationAttr(item.getAttrGroupId());
attrGroupWithAttrsVo.setAttrs(relationAttr);
return attrGroupWithAttrsVo;
}).collect(Collectors.toList());
1.目前的项目中前端中体现的函数式编程比较多,后端更多的还是OOP的思想。
2.在大型的偏向工程话的项目中,使用面向对象的方式方便拓展,更易编写。在项目中的比较小的一些组织模块可以使用函数式编程来提高效率。