js中实现继承的6种方式

268 阅读2分钟

js中实现继承的6种方式

  • 作为一个合格的cv工程师,你可以不会,但我不允许你需要的时候找不到,收集一下继承的6种方式

原型链继承

   function Person(name, age) {
       this.name = name,
       this.age = age,
       this.setName = function () { }
   }
   Person.prototype.setAge = function () { }
   function Student(name, age, price) {
       Person.call(this, name, age)
       this.price = price
   }
   var s1 = new Student('Tom', 20, 15000)
   console.log(s1)
  • 核心:拿父类实例来充当子类原型对象
  • 缺点:
    • 无法继承构造函数中的属性
    • 创建子类实例时,无法向父类构造函数传参
    • 对象中存在多余的属性

借用构造函数继承

     function Person(name, age) {
         this.name = name,
             this.age = age
     }
     Person.prototype.setAge = function () {
         console.log("111")
     }
     function Student(price) {
         this.price = price
         this.setScore = function () { }
     }
     Student.prototype.sayHello = function () { }
     Student.prototype = new Person
     Student.prototype.sayHello = function () { }
     var s1 = new Student(15000)
     var s2 = new Student(14000)
     console.log(s1, s2)
     s1.play.push(4)
     console.log(s1.setAge, s2.setAge)
     console.log(s1.__proto__ === s2.__proto__)
     console.log(s1.__proto__.__proto__ === s2.__proto__.__proto__)
     console.log(s1.__proto__.__proto__.__proto__ === Object.prototype)
  • 核心:借父类的构造函数来增强子类实例,相当于把父类的实例属性复制一份给子类实例
  • call方法:父类构造函数.call(子类实例,参数一,参数二,参数三……)
  • apply方法:父类构造函数.apply(子类实例,[参数一,参数二,参数三……]

原型链+借用构造函数的组合继承

    function Person(name, age) {
        this.name = name,
            this.age = age,
            this.setAge = function () { }
    }
    Person.prototype.setAge = function () {
        console.log("111")
    }
    var p1 = new Person('jack', 15)
    function Student(name, age, price) {
        Person.call(this, name, age)
        this.price = price
        this.setScore = function () { }
    }
    Student.prototype = new Person()
    Student.prototype.constructor = Student//组合继承也是需要修复构造函数指向的
    Student.prototype.sayHello = function () { }
    var s1 = new Student('Tom', 20, 15000)
    var s2 = new Student('Jack', 22, 14000)
    console.log(s1.constructor) //Student
    console.log(p1.constructor) //Person
  • 原型链继承方法
  • 借用构造函数法继承属性
  • 缺点
    • 原型对象存在多余的属性
    • 多次执行父类构造函数

寄生组合继承法(完美版)

    function Person(name, age) {
        this.name = name,
            this.age = age,
            this.setAge = function () { }
    }
    Person.prototype.setAge = function () {
        console.log("111")
    }
    function Student(name, age, price) {
        Person.call(this, name, age)
        this.price = price
        this.setScore = function () { }
    }
    Student.prototype = Person.prototype
    Student.prototype.sayHello = function () { }
    var s1 = new Student('Tom', 20, 15000)
    console.log(s1)
    console.log(s1 instanceof Student, s1 instanceof Person)//true true
    console.log(s1.constructor)//Person
  • 属性:借用构造函数法call,apply,bind继承
  • 方法:原型式继承

原型式继承(继承方法)

   function Person(name, age) {
       this.name = name,
       this.age = age
   }
   Person.prototype.setAge = function () {
       console.log("111")
   }

   function Student(name, age, price) {
       Person.call(this, name, age)
       this.price = price
       this.setScore = function () {}
   }
   Student.prototype = Object.create(Person.prototype)
   Student.prototype.constructor = Student
   var s1 = new Student('Tom', 20, 15000)
   console.log(s1 instanceof Student, s1 instanceof Person) // true true
   console.log(s1.constructor) //Student
   console.log(s1)
  • 核心:先创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回了这个临时构造函数的一个新实例

ES6 class继承

    class Person {
        //调用类的构造方法
        constructor(name, age) {
            this.name = name
            this.age = age
        }
        //定义一般的方法
        showName() {
            console.log("调用父类的方法")
            console.log(this.name, this.age);
        }
    }
    let p1 = new Person('kobe', 39)
    console.log(p1)
    //定义一个子类
    class Student extends Person {
        constructor(name, age, salary) {
            super(name, age)
            this.salary = salary
        }
        showName() { //在子类自身定义方法
            console.log("调用子类的方法")
            console.log(this.name, this.age, this.salary);
        }
    }
    let s1 = new Student('wade', 38, 1000000000)
    let s2 = new Student('kobe', 40, 3000000000)
    console.log(s1.showName === s2.showName)//true
    console.log(s1)
    s1.showName()
  • 继承了属性和方法