«
js之面向对象

时间:2022-4   


继承不是面向对象,所以作为第一层泛化而存在的 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 这个杂交语言的精髓