继承不是面向对象,所以作为第一层泛化而存在的 class 也不是面向对象,面向对象是实体
面向对象字面上就是将对象摆在第一位,而传统面向对象或者说类似JAVA 的方案,更应该叫做面向类,而不是面向对象
class 是从技术实现角度出发,实现的一个比较贴近对象表示的结构而已,但是,很丑陋
对象,即现实事物中与思维中一一对应的概念,天生具有唯一性
实体,是对对象的直接描述,包含对其行为,状态和唯一性的描述
当然,扯这么多都没用,我们直接来看:
function A(){
this.name = ''
this.password = ""
this.log = ()=>{
console.log(this.name+this.password)
}
}
function B(){
let name = ''
let password = ''
return {
name,
password,
log:()=>{
console.lgo(name+password)
}
}
}
不用 this,有什么区别?
首先,B 方便数据交互,因为状态很容易和行为分离:
function B(){
const state = {
name:'',
password:''
}
return {
state,
log:()=>{}
}
}
这个 state,叫做值对象,它保证不变性,能够更加方便地做序列化和消息传递
而方法,附加在 state 上,显式处理 state,可以更方便地处理事件和异步
还有,实体和类的最大区别,是实体直接描述对象,因此具有唯一标识
provide('id', B())
<ContextAsId.Provider value={useB()}/>
这样可以更加方便处理依赖注入(组合关系转聚合关系,即松散耦合关系),更方便处理集合对象
另外,因为没有继承,所以避免了钻石继承问题和里式替换原则导致的问题和工作量
注意,并不是抛弃面向对象转投函数式,不能因为出现了 class 就认为老版本 React 和 Vue 是面向对象而新版本不是(再说 vue 也没 class)
而是函数作为映射(计算)抽象,任何逻辑关系,任何业务行为,都是由函数表征最为合适,而数据结构,应该以目的性为主
真正的面向对象,就应该直接针对实体编程,尽量追求松散耦合(聚合)
而 class 有什么优势?
一个是可读性,自解释性,class 可以很方便地直接转换成文档,同时给编译器提供更多信息
二是可控,class 可以在 console 被打印出来,同时可以约定 implements (实现),强制开发者写代码的规制,强制接口形式
并不是说 class 就是面向对象而 object 就不是了,object,字面意思都是对象,你跟我说不是面向对象?你是不是对面向对象有什么奇怪的误解?
比如 ng,(UI)组件只处理视图,因而最佳实践推荐结构相关处理在组件 class 中完成
但是业务逻辑推荐用 rx,rx 的使用就是值对象+行为抽象流,BehaviorSubject
因此,新版本不仅是面向对象,而且比老版本更加面向对象,因为唯一实体的加入(或者说实体聚合拥有了行为和响应式),同时单一组件值对象可以有多个(老版本只能有一个)
现在比较主流的面向对象观点,会认为对象只是数据结构,而行为,关系,映射,都该是函数的活
函数式和面向对象也不是完全冲突的概念,函数式也能面向对象(state machine)
软件开发就是对现实进行抽象,对抽象进行建模,对建模进行实现,最后再在现实中形成产品
面向对象,函数式缺一不可,无数据结构的函数毫无意义,也没有无成员函数(行为)的对象
别在那当名教徒,天天为几个概念纠结,直接去写,你能明白什么叫做 ——
实体是最佳建模,语言是建模的一切
至于函数式编程是否被拥抱?
Vue3 写个不影响视图变更的变量,直接写 let,你都看到变量了,你跟我说拥抱了函数式?
不不不,极端一点,函数式只有函数,啥都没有
宽松一点,你至少得有个模式识别吧?
再宽松一点,不写变量应该是最低要求吧?
所以,你的最后一句也不成立
函数式和面向对象保持平衡才是最适合工业生产的方式,这也是 Javascript 这个杂交语言的精髓