JavaScript知识点- 继承

98 阅读3分钟

继承

废话不多说,直接上干货

一共有6种方式:
    1. 原型链继承
    2. 经典继承
    3. 组合继承
    4. 原型式继承
    5. 寄生式继承
    6. 寄生组合式继承

1. 原型链继承

子类原型作为父类的实例对象

  • 优点

    1. 继承到父类[挂载在实例上的方法:this.name]
    2. 继承到父类原型上的属性和方法
  • 缺点

    1. 引用类型的属性会在实例之间共享。 [不管生成多少个实例对象,都只是调用了一次父类,访问引用属性时去到的是同一个堆地址]

    2. 子类不能向父类传递参数

  • 代码实现

    function Father() {
    
       }
    father.prototype.getName = function () {
           return this.name
       }
    function Child(params) {
       
    }
    
    // 原型链继承    
    Child.prototype = new Father()
    

2. 经典继承

在子类中调用父类,让子类的this拿到父类中的属性和方法

  • 优点:
    1. 引用类型的属性不被共享。[每生成一个子类实例,都会重新调用一次父类,堆会重新开辟一个地址存储引用属性]
    2. 子类可以向父类传递参数
  • 缺点:
    1. 不能继承父类原型上的方法。
    2. 父类中的方法,每生成一次子类实例,方法都会再创建一遍。
  • 代码实现
function Father(age) {
    
}

function Child() {
   // 经典继承
    Father.call(this,age)
}
let c = new Child()

3. 组合继承:

是原型链继承和经典继承的结合版

  • 优点:有着原型链继承和经典继承的优点。

  • 缺点:在创建第一个子类实例时,会调用两次父类构造函数

  • 代码实现

    function Father(params) {
    
    }
    
    function Child(params) {
        Father.call(this) //经典继承
    }
    Child.prototype = new Father() //原型链继承
    
    let c = new Child()
    

4. 原型式继承(对象)

借助原型链,是Object.crate()的模拟实现 步骤:(函数接收一个对象作为参数) 创建一个临时函数 让函数原型变为 参数对象 返回函数实例对象

  • 优点:让子对象继承到了父对象中的属性

  • 缺点:引用类型属性在子对象中共享

  • 代码实现

    function cloneObj(obj) { 
    
        function fn(params) { //创建临时函数
        
        }
        fn.prototype = obj // 将临时函数的原型变为 obj
    
        return new fn() // 返回函数的实例对象
    }
    

5. 寄生式继承(对象)

比原型式的基础上多了一步增强对象 步骤:(接收子对象和父对象作为参数) 创建一个临时变量,初始化为原型式继承父类原型的对象 增强对象[在这个对象上增加属性] 返回这个对象

  • 优点:子对象继承父对象的属性,并且可以得到一些额外属性[函数中的增强对象操作]
  • 缺点:引用类型属性在实例之间共享
  • 代码实现
    function cloneObj(obj) {
        let clone = Object.create(obj) //复制对象
        clone.setName = function () { //增强对象
            console.log('hello');
        }
        return clone
    }

6. 寄生组合式继承

将组合式和寄生式结合。对组合式继承进行优化,让子类原型和父类间接的联系起来. 减少父类构造函数的调用.

  • 优点:
    1. 减少了父类构造函数的调用次数
    2. 父类中引用属性在实例间不被共享
    3. 子类可以向父类传递参数
  • 代码实现
    function prototype(father,son) {
        // clone是中间人
      let clone = Object.create(father.prototype) // 让clone对象拿到父类原型。为了让后续的子类和父类产生联系

      clone.constructor = son // 将constructor属性指向son【防止constructor丢失】
      son.prototype = clone // 让子类原型变成 clone对象
}