用几个问题 简单聊聊 JavaScript中的面向对象

775 阅读3分钟

JavaScript中的面向对象

  1. 什么是面向对象?

    概念:

    要知道什么是面向对象,我们首先要知道什么是,和对象

    类,即模版.

    在js中我们常用class关键字来声明一个类

    可以看到,下面我用class声明了一个类(以可以说成 定义了一个人类的模版)

    class People {
    constructor(name,age){
       this.name = name
       this.age = age
    }
     eat(){
       console.log(`${this.name} eat something`)
       //...
    }
     speak(){
       console.log(`My name is ${this.name}, age ${this.age}`)
       //...
    }
    }
    

    模版实例化便可得到对象

    下面通过实例化我们定义好的类(模板),就会得到两个拥有各自属性的对象(人)

    当然你也可以实例化更多的对象

    const zhang = new People('张三',34)
    zhang.eat() // 张三 eat something
    zhang.speak() // My name is 张三, age 34`const li = new People('李四',32)
    zhang.eat() // 李四 eat something
    zhang.speak() // My name is 李四, age 32`
    

    结论:

    面向对象的方法主要是把事物给对象化(结构化),包括其属性和行为。面向对象编程更贴近实际生活的思想(更加抽象,便于程序员理解)。总体来说面向对象的底层还是面向过程,面向过程抽象成类,然后封装,方便使用(复用),就是面向对象(万物皆对象)。

  2. 面向对象有什么特点?

    1. 继承 (子类继承父类):

      我们继续使用上面定义的People类作为基准,简单的演示一下继承,

      下面创建一个新的类继承People类,

      // extends 表示继承
      class Student extends People {
       constructor(name,age,position){
         super(name,age) // 因为name和age是已经在父类里定义好的参数,我们只需要使用super()函数传递即可
         this.position = position
      }
       
       job(){
         console.log(`My position in the class is ${this.position }`)
         //...
      }
      }
      

      之后我们实例化Student类,

      可以看到,虽然Student类里没有定义eat( )speak( ) 方法,但是我们仍能通过实例化的对象进行调用,这就是继承

      const xiaoming = new Student('小明',12,'副班长')
      xiaoming.eat() // 小明 eat something
      xiaoming.speak() // My name is 小明, age 12`
      xiaoming.job() // My position in the class is 副班长
      

      当然你也可以基于People类,创建一些诸如 Doctor , Police 等等的子类

      由此可见,继承可以将公共方法抽离出来,提高复用,减少代码冗余.

    2. 封装 (数据的权限,保密的方法):

      封装,故名思义就是封起来,装起来,不过在面向对象的封装里,还多了一层含义,就是权限(谁能看见,谁能使用)

      由此,引出了三个关键字:

      • public 完全开放
      • protected 对子类开放
      • private 对自己开放

      我们可以在程序中,使用上面的关键字,来对一个类里面的的属性,以及方法施加权限.

      由于目前ES6(JavaScript)暂不支持这三个关键字,下面使用TypeScript进行演示:

      // 父类
      class People {
       namestring;
       agenumber;
       protected weightnumber// 对子类开放的 weight属性
       constructor(name, age, weight) {
         this.name = name;
         this.age = age;
         this.weight = weight;
      }
       eat() {
         console.log(`${this.name} eat something`);
         //...
      }
       speak() {
         console.log(`My name is ${this.name}, age ${this.age}`);
         //...
      }
       protected myWeight() {
         console.log(`My weight is ${this.weight}`);
         //...
      }
      }
      ​
      // 子类
      // extends 表示继承
      class Student extends People {
       positionstring;
       private girlfriendboolean// 只允许自己访问
       constructor(name, age, weight, position, girlfriend) {
         super(name, age, weight); // 因为name和age是已经在父类里定义好的参数,我们只需要使用super()函数传递即可
         this.position = position;
         this.girlfriend = girlfriend;
      }
      ​
       job() {
         console.log(`My position in the class is ${this.position}`);
         //...
      }
       haveGirlfriend() {
         this.myWeight() // 只允许在子类访问
         console.log(`girlfriend is ${this.girlfriend}`);
         //...
      }
      }
      ​
      const xiaoming = new Student("小明"1285"副班长"false);
      // xiaoming.myWeight() 报错:属性“myWeight”受保护,只能在类“People”及其子类中访问
      // xiaoming.weight 报错:属性“weight”受保护,只能在类“People”及其子类中访问。
      // xiaoming.girlfriend 报错:属性“girlfriend”为私有属性,只能在类“Student”中访问。
      xiaoming.haveGirlfriend() // My weight is 85   girlfriend is false
      

      由此我们可以看到封装带来的好处:

      • 减少耦合,不该外漏的不外漏.
      • 利于数据,接口的权限管理.
    3. 多态 (同一接口的不同实现):

      • 保持了子类的开放性和灵活性

        如何理解呢,就那上边我们定义的People类来说明,当我们定义了一个People的父类,那么相应的,我们可以在People类的基础上,向下延伸,去定义继承于(基于)People类的各种子类,诸如Student、 Doctor 、Police* * 等等等等,这些子类都拥有属于自己独特的行为,以及属性,但是他们的基准都是People类,这就是我们所说的多态.

      • 面向接口编程

  3. 为什么选择面向对象?

    1. 程序执行 : 顺序、判断、循环 —— 结构化.
    2. 面向对象 其实就是 数据结构化.
    3. 对于计算机 (对于程序猿) 结构化才是最简单,也是最易于管理的.
    4. 编程应该 简单&抽象 抽象之后才能简单,简单的前提就是要抽象,将代码抽象化也更易于人类大脑的理解.
  4. 什么是UML类图?

    表达类与类之间的关系的图,就叫类图.

    在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)

    更多详解见下方博客链接:

    www.jianshu.com/p/57620b762…


\