美文网首页
JS继承的6种方式及优缺点

JS继承的6种方式及优缺点

作者: OriX0 | 来源:发表于2020-07-03 21:51 被阅读0次

    参考文章:一文看懂 JS 继承

    构造函数继承
    优势
    • 可以定义私有属性方法

    • 子类传递参数给父类

    劣势
    • 不能定义共享的属性方法

    • 共享的属性方法需要写在外面 失去了封装性

    :chestnut:
    
    let share = [1, 2, 3];
    
    function log () {
    
      console.log(this.name);
    
    }
    
    function Parent (name, friends) {
    
      this.name = name;
    
      this.friends = friends;
    
      this.share = share;
    
      this.log = log;
    
    }
    
    function Child (name, friends, gender) {
    
      Parent.call(this, name, friends);
    
      this.gender = gender;
    
    }
    
    
    原型链继承

    原型链模式需要手动重新绑定 constructor 而且不能定义私有变量

    优势
    • 可以定义公有属性和方法
    劣势
    • 无论是定义还是继承都需要手动修改 constructor

    • 封装性一般

    • 不能定义私有属性方法

    • 没办法向父类传递参数

    :chestnut:
    
    function Parent () { };
    
    Parent.prototype = {
    
      constructor: Parent,// 需要手动绑定constructor
    
      name: 'oli',//不能定义私有属性 全部都是公有的
    
      friends: ['alice', 'troy'],// 方法和属性都是公有的 所有实例都引用这个
    
      log: function () {
    
        return this.name
    
      }
    
    }
    
    // 封装性一般
    
    function Child () { };// 没办法向父类传递参数
    
    Child.prototype = new Parent();// 使用new 操作符创建并重写prototype
    
    console.log(Child.prototype.constructor);
    
    Child.prototype.constructor = Child; // 每次继承都需要手动修改constructor
    
    
    组合继承 原型链继承+构造函数继承
    优势
    • 公有的写在原型

    • 私有的卸载构造函数

    • 可以向父类传递参数

    劣势
    • 需要手动绑定constructor

    • 封装性一般

    • 重复调用父类性能损耗

    :chestnut:

    
    function Parent (name, friends) {
    
      // 私有的部分
    
      this.name = name;
    
      this.friends = friends;
    
    }
    
    Parent.prototype = {
    
      // 公有的写这里
    
      constructor: Parent,// 需要手动绑定
    
      share: [1, 2, 3],
    
      log: function () {
    
        return this.name;
    
      }
    
    }
    
    // 封装性一般
    
    function Child (name, friends, gender) {
    
      Parent.call(this, name, friends); // 这里调用了一次Parent
    
      this.gender = gender;
    
    }
    
    Child.prototype = new Parent(); // 这里又调用了一次Parent
    
    Child.prototype.constructor = Child;//需要手动修改constructor
    
    
    原型式继承

    原型式继承方法直接使用ES5object.create方法

    object.create原理
    • 创建一个构造函数,构造函数的原型指向对象,

    • 调用 new 操作符创建实例,并返回这个实例,

    • 本质是一个浅拷贝

    优点
    • 父类方法可以复用
    缺点
    • 父类引用属性全部被共享

    • 子类不可传递参数给父类

    :chestnut:

    
    let parent = {
    
      name: 'parent',
    
      share: [1, 2, 3],// 父类的属性全部被子类共享
    
      log: function () {  // 父类的方法可以复用
    
        return this.name;
    
      }
    
    }
    
    let child = Object.create(parent);
    
    
    寄生式继承

    在原生式继承的基础上为子类增加属性和方法 二次封装

    优势
    • 父类方法可以复用

    • 增加了别的属性和方法

    劣势
    • 父类引用属性全部被共享

    • 子类不可传递参数给父类

    :chestnut:

    
    let parent = {
    
      name: 'parent',
    
      share: [1, 2, 3],
    
      log: function () {
    
        return this.name;
    
      }
    
    }
    
    function create (obj) {
    
      let cloneObj = Object.create(obj);
    
      cloneObj.print = function () { // 增加了一些属性和方法
    
        console.log(this.name)
    
      }
    
      return cloneObj;
    
    }
    
    let child = create(parent);
    
    
    寄生组合式继承

    杂糅了原型链式、构造函数式、组合式、原型式、寄生式而形成的一种方式:

    主要是解决了组合继承的唯一缺点:多次调用Parent

    优点:
    • 公有的写在原型

    • 私有的写在构造函数

    • 可以向父类传递参数

    • 不会重复调用父类

    缺点
    • 需要手动绑定constructor

    • 需要调用额外的方法 封装性一般

    :chestnut:

    
    function Parent (name, friends) {
    
      this.name = name;
    
      this.friends = friends;
    
    }
    
    Parent.prototype = {
    
      constructor: Parent,//需要手动绑定constructor
    
      share: [1, 2, 3],
    
      log: function () {
    
        return this.name
    
      }
    
    }
    
    function Child (name, friends, gender) {
    
      Parent.call(this, name, friends);
    
      this.gender = gender;
    
    }
    
    function proto(child, parent) {
    
      let clonePrototype = Object.create(parent.prototype)
    
      child.prototype = clonePrototype
    
      child.prototype.constructor = child
    
    }
    
    proto(Child,Parent);
    
    
    ES6 class

    :chestnut:

    
    class Parent {
    
        constructor(name, friends) { // 该属性在构造函数上,不共享
    
            this.name = name
    
            this.friends = friends
    
        }
    
        log() { // 该方法在原型上,共享
    
            return this
    
        }
    
    }
    
    Parent.prototype.share = [1, 2, 3] // 原型上的属性,共享
    
    class Child extends Parent {
    
        constructor(name, friends, gender) {
    
            super(name, friends)
    
            this.gender = gender
    
        }
    
    }
    
    

    相关文章

      网友评论

          本文标题:JS继承的6种方式及优缺点

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