JS继承的5种方式

156 阅读1分钟

第一种: 借助call

      function Parent1() {
        (this.name = "parent1"),
          function () {
            console.log("方法");
          };
      }
      function Child1() {
        Parent1.call(this);
        this.type = "child1";
      }
      let a = new Child1();
      console.log(a); //name: "parent1" type: "child1"
      //虽然能够拿到父类的属性值,
      //但是问题是父类原型对象中一旦存在方法那么子类无法继承

image.png

第二种: 借助原型链

      function Parent2() {
        this.name = "parent2";
        this.play = [1, 2, 3];
      }
      function Child2() {
        this.type = "child2";
      }
      Child2.prototype = new Parent2();
      console.log(new Child2());
      var s1 = new Child2();
      var s2 = new Child2();

      s1.play.push(4);
      console.log(s1.play, s2.play); //(4) [1, 2, 3, 4] (4) [1, 2, 3, 4]
      // 明明我只改变了s1的play属性,为什么s2也跟着变了呢?
      // 很简单,因为两个实例使用的是同一个原型对象

image.png

注意的点:实际上这个方法主要实现了可以继承父的方法

第三种:将前两种组合

      function Parent3() {
        this.name = "parent3";
        this.play = [1, 2, 3];
      }
      function Child3() {
        Parent3.call(this);
        this.type = "child3";
      }
      Child3.prototype = new Parent3();
      var s3 = new Child3();
      var s4 = new Child3();
      console.log(s3);

      s3.play.push(4);
      console.log(s3.play, s4.play); //(4) [1, 2, 3, 4] (3) [1, 2, 3]

      //但是这里又徒增了一个新问题,
      //那就是Parent3的构造函数会多执行了一次(Child3.prototype = new Parent3();)

image.png

注意的点:

  • 上一个方法相当于通过原型链访问父类上的属性,同一个父类,所以属性是同一个

  • 而这个方法中,call相当于child3上也有name和play了,执行后每个实例上都有这些属性了,所以互不影响

第四种: 组合继承的优化1

      function Parent4() {
        this.name = "parent4";
        this.play = [1, 2, 3];
      }
      function Child4() {
        Parent4.call(this);
        this.type = "child4";
      }
      Child4.prototype = Parent4.prototype;
      var s3 = new Child4();
      var s4 = new Child4();
      console.log(s3);

      // 子类实例的构造函数是Parent4,显然这是不对的,应该是Child4

image.png

第五种: 寄生组合继承

      function Parent5() {
        this.name = "parent5";
        this.play = [1, 2, 3];
      }
      function Child5() {
        Parent5.call(this);
        this.type = "child5";
      }
      Child5.prototype = Object.create(Parent5.prototype);
      Child5.prototype.constructor = Child5;

      var s3 = new Child5();
      var s4 = new Child5();
      console.log(s3);

image.png