Thoroughly understand the three inheritance of prototype chain and Class inheritance of ES6

Prototype inheritance

Advantages: the same prototype object

Disadvantages: the prototype object cannot be modified, which will affect all instances

 function Animal(){
         this.type = "animal"
      };
      
      function Cat(name,color){
         this.name = name;
         this.color = color;
      };
      Cat.prototype = new Animal();
      var c1 = new Cat('x','white');
      var c2 = new Cat('t','black');
      c1.type   //'animals'

It can be seen that the Cat instance inherits the type attribute of Animal

expand:

function Animal(){   //Animal object   
         this.type = 'animal'
      };
      function Cat(name,color){   //Cat object  
         this.name = name;
         this.color = color;
         this.type='I'm a cat';
      };
      Cat.prototype = new Animal();  //The prototype object of the cat points to the animal function
      var cat1 = new Cat("Xiao Huang","yellow");
      var cat2 = new Cat("Xiao Hei","black");
      console.log(cat1.type); // 'I'm a cat'
      console.log(cat2.type); // 'I'm a cat'
      //Want to get the value of the Animal member
      console.log(cat1.__proto__.type); //'animals'
      console.log(cat2.__proto__.type); //'animals'

From the output of the above code block, we can see that if both the current constructor and the parent Animal have attributes, Cat1 Type gets the type attribute in the current constructor Cat. If you want to get the attribute in the prototype object Animal, you must pass Cat1__ proto__. Type. If Cat1__ proto__. Type ='xx 'to modify the attributes on the prototype object, then all instances will be affected, which is also a major disadvantage of prototype inheritance.

When we access the properties of a prototype object__ proto__ It is obtained level by level. When the inheritance relationship is very complex and you don't know how to inherit the relationship, you can only look up layer by layer.

Constructor inheritance

Advantages: modifying prototype objects does not affect all instances, and each has independent properties

Disadvantages: the members of the parent class will be created multiple times, which is redundant and not the same prototype object

★ only members can be copied through call/apply, and prototype objects will not be copied.

 function Animal(){  
         this.type = "animal"
     };
     function Cat(name,color){       
         Animal.apply(this);   //Copy members of an Animal object to a Cat object
         this.name = name;
         this.color = color;
     };
     var cat1 = new Cat("Xiao Huang","yellow"); 
     var cat2 = new Cat("Xiao Hei","black");
     cat1.type = 'I'm Xiao Huang';
     cat2.__proto__.type = 'I'm an animal';
     console.log(cat1.type); //'I'm Xiao Huang' cat1 was modified
     console.log(cat2.type); //"Animals"

From the output of the above code block, it can be seen that since apply() changes the direction of this, it is equivalent to copying the members of the Animal object to the Cat object. When cat2 passes__ proto__ Changing the type attribute of the parent class Animal will not affect its own type attribute. Only through Cat1 Type = '' to change. At this time, Animal and Cat do not point to the same prototype object. Each time a subclass is created, the parent class member must be created. There is redundancy, which is also a major disadvantage of constructor inheritance.

Combinatorial inheritance

Is there a way to avoid that the attributes of subclass instances inherited by the prototype are easily affected by the prototype object, and the constructor makes the subclass and parent class not point to the same prototype object, which has the defect of redundancy?

function Animal(){   
      this.type = 'animal'
   };
  Animal.prototype.eat = function(){console.log('Eat cat food')};  
  function Cat(name,color){  
     this.name = name;
     this.color = color;
     Animal.call(this); 
  };
  Cat.prototype = new Animal();  
  var cat1 = new Cat("Xiao Huang","yellow");
  var cat2 = new Cat("Xiao Hei","black");
  cat1.type = 'I'm Xiao Huang';  //Modify properties in the current constructor
  cat2.__proto__.type = 'I'm an animal';//The value of the prototype object is modified, but it does not affect the values of CAT1 and cat2
  console.log(cat1.type); //'I'm Xiao Huang' / / the value change of the prototype object does not affect the constructor value
  console.log(cat2.type); //'animals'
  console.log(cat2.__proto__.type);  //'I'm an animal
  cat1.eat(); //You can also call the eat() method in the prototype object
   

From the output of the above code block, you can see that cat2__ proto__. Type = 'I'm an Animal' modifies the prototype attribute, which does not affect the type in instance cat2, indicating that the instance of the subclass will not be affected by the change of the object attribute on the parent prototype. Cat.prototype = new Animal() makes them belong to the same prototype object. In this way, the eat() method on the prototype object of the parent Animal can still be obtained in the instance object of cat. This solves the problem of constructor inheritance method. Because the subclass and parent class do not point to the same prototype object, the parent class members of a subclass must be created once every time they are created, which has the disadvantage of redundancy.

Class inheritance

class A {
        constructor(){
            this.a = 'a';
        }
    };


    class B extends A{   //Means to inherit all attributes and methods of class A through the extends keyword
        constructor(){
            super();  //Constructor representing the parent class
            this.b = 'b';
        }
    };

    var a = new A();
    var b = new B();
    b.a     //"a"

Class B inherits all properties and methods of class A through the extends keyword.

The subclass must call the super () method in the constructor type, otherwise the new instance will report an error. Super can be used as either a function or an object. When used as a function, it represents the constructor of the parent class. ES6 requires that the constructor of subclasses must execute the super function once.

So what is the specific instance of super as an object?

class A{
    p(){
        return 2;
    }
}

class B extends A{
    constructor(){
        super();
        console.log(super.p());//2. As the object, super is actually class A
    }
}

let b = new B;

At this time, super The super of P () is an object, which is actually equivalent to time classA.

expand:

class A {
        constructor(x,y){
            this.x = x;
            this.y = y;
        }
        toString(){
            return this.x
        }
    };

    class B extends A{   //Means to inherit all attributes and methods of class A through the extends keyword
        constructor(x,y,b){
            super(x,y);  //Constructor representing the parent class
            this.b = b;
        }
    };
   
    let b = new B('333','444','abc');
    b.x    //'333'
    b.y    //'444'
    b.toString()    //'abc'

You need to add parameters in super() to pass data to attributes and methods that inherit class A.

Keywords: Javascript Front-end ECMAScript

Added by dw89 on Sat, 05 Mar 2022 01:57:58 +0200