美文网首页
JSES5继承

JSES5继承

作者: RadishHuang | 来源:发表于2021-07-06 13:31 被阅读0次

    前面文章有提到过原型和原型链的文章,总结下,对象的proto指向的是函数的原型。通过这种方式,可以做到原始的继承方法。

    • 理解概念constructor构造函数,是一种用于创建和初始化创建的对象的特殊方法。一般理解constructor指向的都是谁来创建的。
      1、constructor是一种函数模板,用于创建对象。
      2、constructor是一个属性,告诉实例,是谁创建了实例。
    constructor
    • 原型链就是通过这种方式,可以一层一层的找。constructor就像是族谱一样,开发中我们希望谁是对象的爸爸,谁是对象的爷爷,是清晰的,明确的。

    接下来进入正题,关于es5的原型链继承是怎么回事,我们先看下如果不加constructor是什么一个情况。

    不加constructor

    打印出来的constructor指向的是father的类。然而我们new出来的对象其实是child。我们可以看到这个对象的构造函数已经不存在了,所以我们找constructor的时候根据原型链会一层层往上找,找到了它爷爷的构造函数。

    加constructor

    原型链继承

    function Father() {
      this.name = ['我是父亲'];
      this.sex = '男'
    }
    Father.prototype.getName = function () {
      console.log(this.name);
    }
    function Child(params) {
      this.name.push(params);
      this.age = 18;
    }
    Child.prototype = new Father();
    // 所有涉及到原型链继承的继承方式都要修改子类构造函数的指向,否则子类实例的构造函数会指向SuperType。
    Child.prototype.constructor = Child;
    Child.prototype.say = function () {
      console.log(this.name + 'say hi');
    }
    let child1 = new Child('child1');
    let child2 = new Child('child2');
    child1.name[0] = '我是change child2';
    
    
    console.log(child1.getName())  // ["我是change child2", "child1", "child2"]
    console.log(child2.getName()) // ["我是change child2", "child1", "child2"]
    
    • 上面的代码就是经典的原型链继承,原型链继承有一个很致命的缺点。
    • 父属性是共用的
    • 子类构造函数的时候,没办法给父类传参数。

    上面的代码运行结果,会发现,child1添加值,child2也会变,child2修改值,child1也会变。这个不是我们想要的。

    构造函数继承

    • 通过call方法,创建的对象指向对象本身。这样就实现了每个对象不会共用父属性。
    • 但是也有一个致命的缺点,原型全部丢失了。就是没办法调用到getName的方法
    function Father(type) {
      this.name = ['我是父亲'];
      this.sex = '男'
      this.type = type;
    }
    Father.prototype.getName = function () {
      console.log(this.name);
    }
    function Child(name, type) {
      Father.call(this, type);
      this.name.push(name);
      this.age = 18;
    }
    let child1 = new Child('child1', 1);
    let child2 = new Child('child2', 2);
    child2.name[0] = '我是change child2';
    console.log(child1.name)  // ["我是父亲", "child1"]
    console.log(child2.name) // ["我是change child2", "child2"]
    

    组合继承

    • 故名思议就是把两个的优点都拿过来,缺点都摒弃。
    
    function Father(type) {
      this.name = ['我是父亲'];
      this.sex = '男'
      this.type = type;
    }
    Father.prototype.getName = function () {
      console.log(this.name);
    }
    function Child(name, type) {
      Father.call(this, type);
      this.name.push(name);
      this.age = 18;
    }
    Child.prototype = new Father();
    Child.prototype.constructor = Child;
    let child1 = new Child('child1', 1);
    let child2 = new Child('child2', 2);
    child2.name[0] = '我是change child2';
    console.log(child1.name) // ["我是父亲", "child1"]
    console.log(child2.name) // ["我是change child2", "child2"]
    console.log(child1.getName()) // ["我是父亲", "child1"]
    console.log(child2.getName()) // ["我是change child2", "child2"]
    
    • 优点就是原型链继承和构造函数继承的共同有点
    • 父类的方法可以被复用
    • 父类的引用属性不会被共享
    • 子类构建实例时可以向父类传递参数
    • 缺点调用了两次父类的构造函数。

    相关文章

      网友评论

          本文标题:JSES5继承

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