面向对象(三)

94 阅读2分钟

Javascript中的类

  我们上一章聊到的构造函数,从很多面向对象语言过来的开发者都不习惯称为构造函数,习惯称之为类(class),从编程范式来看,确实可以称之为

面向对象有三大特性:封装、继承、多态

  • 封装:我们前面将属性和方法封装到一个类中,可以称之为封装的过程
  • 继承:继承是面向对象中非常重要的,不仅仅可以减少重复代码的数量,也是多态前提(纯面向对象中)
  • 多态:不同的对象在执行时表现出不同的形态 我们之前的构造函数的赋值过程就是封装,我们接下来要讲的重点是继承。在了解继承之前,我们要了解Javascript中的原型链(prototype chain)

Javascript中的原型链

原型链(prototype chain)是由一个一个的原型对象不断向上攀升连接所形成的链条,但是这个链条实际上是虚拟的,只是形象地表示原型对象之间的关系。

   const obj = {
     name: 'zengge',
     age: 22
   }
   console.log(obj.height)

我们此时打印obj.height,显然会提示undefined。这是因为我们obj本身并没有height这个属性,但是实际上js的查找机制并不是只在当前对象中查找,而是会沿着原型链查找,直到查找到原型链的顶端。如果我们在obj的原型对象__proto__上增加一个height属性,那么我们就可以查找并打印出来这个属性。

    const obj = {
     name: 'zengge',
     age: 22
   }
   obj.__proto__ = {
     height: 1.88
   }
   console.log(obj.height)

image.png
以此类推,我们只要在这条原型链上任意一个原型对象上设置了height属性,那么都可以被查找并打印出来。

    const obj = {
     name: 'zengge',
     age: 22
   }
   obj.__proto__.__proto__.__proto__ = {
     height: 1.88
   }
   console.log(obj.height)

image.png

Javascript中的继承

我们现在有两个构造函数TeacherStudent分别有各自的方法和属性,但是也有共同的方法和属性,代码如下:

   function Teacher(name, age, title) {
     this.name = name
     this.age = age
     this.title = title
   }
   Teacher.prototype.sayHello = function() {
     console.log(`你好我是${this.name}`)
   }
   Teacher.prototype.teach = function() {
     console.log(`${this.name}teaching`)
   }
   
   function Student(name, age, course) {
     this.name = name
     this.age = age
     this.course = course
   }
   Student.prototype.sayHello = function() {
     console.log(`你好我是${this.name}`)
   }
   Student.prototype.studying = function() {
     console.log(`${this.name}studying`)
   }

其中name,age是公共属性,sayHello是公共方法,title,course是私有属性,teach,studying是私有方法。这样会造成代码冗余,所以我们需要一个公共的类来继承他们的公共部分。这样就需要用到Javascript中的继承。

   function Person() {
   }
   Person.prototype.sayHello = function() {
     console.log(`你好我是${this.name}`)
   }
   
   function Teacher(title) {
     this.title = title
   }
   Teacher.prototype = new Person()
   Teacher.prototype.teach = function() {
     console.log(`${this.name}teaching`)
   }
   
   function Student(course) {
     this.course = course
   }
   Student.prototype = new Person()
   Student.prototype.studying = function() {
     console.log(`${this.name}studying`)
   }
   const teacher = new Teacher('Math')
   const student = new Student('Math')
   stu.sayHello()
   teacher.sayHello()

我们创建了一个Person构造函数,将Person放到了TeacherStudent的原型链上,这样就充当了父类,可以访问父类上公共的属性或者方法。