美文网首页
再学JS--继承的多种方式以及优缺点

再学JS--继承的多种方式以及优缺点

作者: Territory_Cheng | 来源:发表于2020-06-28 16:52 被阅读0次

    原型链继承

    function Parent() {
        this.name = ['zhangsan']
    }
    
    Parent.prototype.getName = function() {
        console.log(this.name)
    }
    
    function Child() {
    
    }
    
    Child.prototype = new Parent()
    
    var child1 = new Child()
    
    child1.getName()  ['zhangsan']
    

    缺点:

    1. 引用类型的属性被所有实例共享

      child1.name.push('lisi')
      child1.getName()  // ['zhangsan', 'lisi']
      var child2 = new Child()
      child2.getName()  // ['zhangsan', 'lisi']
      
    2. 在创建child的实例时,不能像Parent传参

    借用构造函数(经典继承)

    function Parent() {
        this.name = ['zhangsan', 'lisi']
    }
    
    function Child() {
        Parent.call(this)
    }
    
    var child1 = new Child()
    child1.name.push('wangwu')
    console.log(child1.name)  // ['zhangsan', 'lisi', 'wangwu']
    
    var child2 = new Child()
    console.log(child2.name)  // ['zhangsan', 'lisi']
    

    优点:

    1. 避免了引用类型的属性被所有实例共享
    2. 可以在Child中向Parent传参
    function Parent(name) {
        this.name = name
    }
    
    function Child(name) {
        Parent.call(this, name)
    }
    
    var child1 = new Child('zhangsan')
    console.log(child1.name)  // zhangsan
    
    var child2 = new Child('lisi')
    console.log(child2.name)  // lisi
    

    缺点:

    1. 方法都在构造函数中定义,每次创建实例都会创建一遍方法

    组合继承(原型链继承+经典继承)

    function Parent(name) {
        this.name = name
        this.colors = ['red', 'blue', 'green']
    }
    
    Parent.prototype.getName = function() {
        console.log(this.name)
    }
    
    function Child(name, age) {
        Parent.call(this, name)
        this.age = age
    }
    
    Child.prototype = new Parent()
    
    var child1 = new Child('zhangsan', 18)
    
    child1.colors.push('black')
    
    console.log(child1.name)  // zhangsan
    console.log(child1.age)  // 18
    console.log(child1.colors)  // ['red', 'blue', 'green', 'black']
    
    var child2 = new Child('lisi', 16)
    console.log(child2.name)  // lisi
    console.log(child2.age)  // 16
    console.log(child2.colors)  // ['red', 'blue', 'green']
    

    优点:

    融合原型链继承和构造函数的优点,是JavaScript中最常用的继承模式

    原型式继承

    function createObj(o) {
        function F() {}
        F.prototype = o
        return new F()
    }
    

    就是ES5 Object.create的模拟实现,将传入的对象作为创建的对象的原型。

    缺点:

    包含引用类型的属性值始终都会共享相应的值,这点跟原型链继承很像

    function createObj(o) {
        function F() {}
        F.prototype = o
        return new F()
    }
    
    var person = {
        name: 'zhangsan',
        friends: ['lisi']
    }
    
    var person1 = createObj(person)
    var person2 = createObj(person)
    
    person1.name = 'person1'
    console.log(person1.name)  // person1
    console.log(person2.name) // zhangsan
    
    person1.friends.push('wangwu')
    console.log(person2.friends)  // ['lisi', 'wangwu']
    

    注意:修改person1.name的值,person2.name的值并未发生改变,并不是因为person1和person2有独立的值,而是因为person1.name = ’person1‘,给person1添加了name值,并非修改了原型上的name值。

    寄生式继承

    创建个仅用于继承封装过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象

    function createObj(o) {
        var clone = Object.create(o)
        clone.sayName = function() {
            console.log('hi')
        }
        return clone
    }
    

    缺点:跟借用构造函数模式一样,每次创建对象都会创建一遍方法。

    寄生组合式继承

    组合式继承最大的缺点是会调用两次父构造函数

    一次是设置子类型实例的原型的时候

    Child.prototype = new Parent()
    

    一次在创建子类型实例的时候

    var child1 = new Child('zhangsan', 18)
    // new的时候,会执行
    Parent.call(this, name)
    

    如何避免这一次的重复调用

    function Parent(name) {
        this.name = name
        this.colors = ['red', 'blue', 'green']
    }
    
    Parent.prototype.getName = function() {
        console.log(this.name)
    }
    
    function Child(name, age) {
        Parent.call(this, name)
        this.age = age
    }
    
    // 关键步骤
    var F = function() {}
    F.prototype = Parent.prototype
    
    Child.prototype = new F()
    
    var child1 = new Child('zhangsan', 18)
    

    封装一下这个继承方法

    function object(o) {
        function F() {}
        F.prototype = o
        return new F()
    }
    
    function prototype(child, parent) {
        var prototype = object(parent.prototype)
        prototype.constructor = child
        child.prototype = prototype
    }
    

    相关文章

      网友评论

          本文标题:再学JS--继承的多种方式以及优缺点

          本文链接:https://www.haomeiwen.com/subject/douwfktx.html