前端实现继承的几种方式

900 阅读2分钟

继承实现以下需求

  1. Student 继承Person
  2. Person 包含一个实例变量 name, 包含一个方法 printName
  3. Student 包含一个实例变量 score, 包含一个实例方法printScore
  4. 所有Person和Student对象之间共享一个方法

es6 实现继承

 class Person {
        constructor(name) {
            this.name = name;
        }
        printName() {
            console.log('This is printName');
        }
        commonMethods() {
            console.log('我是共享方法');
        }
    }

    class Student extends Person {
        constructor(name, score) {
            super(name);
   // super作为函数被调用时,代表父类的构造函数,相当于Person.prototype.constructor.call(this)
            this.score = score;
        }
        printScore() {
            console.log('This is printScore');
        }
    }

    let stu = new Student('小红', 1);
    let person = new Person('小紫');
    console.log(stu.commonMethods === person.commonMethods);//true
    console.log('stu', stu)

核心: 使用extends表明继承自那个父类,并且在自构造函数中必须调用super. class的本质还是函数

tips

  1. constructor 是类的默认方法,通过new 命令生成对象实例时,会自动执行constructor。一个类必须有constructor,如果没有显示定义,一个空的constructor会被添加
  2. constructor的作用就是表名某个实例对象是由哪个构造函数产生的
  3. constructor是表示原型和实例关联关系的一个属性。所以当修改原型对象的时候,也会修改constructor。
  4. Star.prototype = {}给原型重新赋值,此时会丢失构造器,我们需要手动定义构造器,指回构造函数本身

组合继承

 function Person(name) {
       this.name = name
       this.printNama = function () {
           console.log('Person printNama ');
       }
   }
   Person.prototype.commen = function () {
       console.log('commenMethods')
   }
   function Student(name, score) {
       Person.call(this, name)
       this.score = score
       this.printScore = function () {
           console.log('Student printScore');
       }
   }
   Student.prototype = new Person()
   let person = new Person('小红', 30)
   let student = new Student('小敏', 20)
   console.log(Student.commen === Person.commen)
   console.log('student', student)
   console.log('person', person)

tips

  1. 组合继承,就是利用原型链来实现方法共享,利用构造函数来实现属性属性共享.通过在原型上定义方法,实现了函数的复用,又能保证每个实例有自己的属性

寄生式继承

 function Person(name) {
       this.name = name
       this.printNama = function () {
           console.log('Person printNama ');
       }
   }
   Person.prototype.commen = function () {
       console.log('commenMethods')
   }
   function Student(name, score) {
       Person.call(this, name)
       this.score = score
       this.printScore = function () {
           console.log('Student printScore');
       }
   }
   Student.prototype =  Object.create(Person.prototype) 
   let person = new Person('小红', 30)
   let student = new Student('小敏', 20)
   console.log(Student.commen === Person.commen)
   console.log('student', student)
   console.log('person', person)

「tips」

寄生式继承: 主要就是解决new两次和 执向同一个原型的问题,所以将new Person() 换成 Person.prototype。 并且使用Object.create()

对比

class 继承: 使用extends表明继承自那个父类,并且在子构造函数中调用super,进行传参。

原型链继承:由于两个构造函数,指向同一个原型对象,一个改变,另一个也会改变

构造函数继承:不能继承实例对象的方法

组合继承:继承的时候,实例化一次,自己实例化一次

寄生式继承:解决了实例化两次的问题,并且使用Object.create() 实现了 创建一个新对象,使用现有的对象来提供新创建的对象的proto

Object.create()必须接收一个对象参数,创建的新对象的原型指向接收的参数对象,new Object() 创建的新对象的原型指向的是 Object.prototype. (表述有点啰嗦,简洁点说就是前者继承指定对象, 后者继承内置对象Object)