Inheritance is an important point in JavaScript, including constructor inheritance, prototype chain inheritance, combinatorial inheritance, parasitic inheritance, and combinatorial parasitic inheritance.

Constructor inheritance

Features: As the name implies, only the parent class constructor inherits, not the traditional sense of inheritance. How to do it: A subclass calls the parent constructor with a call and passes in this. After executing the parent constructor, the subclass has the properties and methods defined by its parent.

Function Flower(){this.colors = [' red ',' yellow ']; this.print = function(){ console.log(this.colors) } } function Violate(){ Flower.call(this) } var child1 = new Violate() Var child2 = new Violate() console.log(child1.print()) // [" red ", "yellow "] console.log(child2.print()) // [" red ", "Yellow"] child1. Colors. Push (' purple ') console. The log (child1. Print ()) / / [" red ", "yellow", "purple"] the console. The log (child2. Print ()) / / [" red ", "Yellow "] // Only the property value of child1 is changedCopy the code

Advantages: All base properties are independent and not affected by other instances. Disadvantages: All the methods and attributes that you want to share are also independent, and there is no way to update all the child instances at the same time by modifying one part of the parent class. Also, the parent constructor is called once every time a subclass is created, so each child instance copies the contents of the parent function, which can affect performance if the parent class is large.

Prototype chain inheritance

Characteristics: Inheritance using the characteristics of a prototype chain is not true inheritance. Implementation: The characteristic of the prototype chain is that if an object cannot find a property, it will look up its prototype until the end of the prototype chain. We assign an instance of the parent function to the prototype of the child function, and the constructor of the child function has changed because of the assignment and needs to point back to the self-generated constructor.

Function Flower(){this.colors = [' red ',' yellow ']; this.print = function(){ console.log(this.colors) } } function Violate(){ } Violate.prototype = new Flower() Violate.prototype.constructor = Violate var child1 = new Violate() var child2 = new Violate() The console. The log (child1. Print ()) / / / "red", "yellow" console. The log (child2. Print ()) / / [" red ", "Yellow"] child1. Colors. Push (' purple ') console. The log (child1. Print ()) / / [" red ", "yellow", "purple"] the console. The log (child2. Print ()) / / [" red ", "Yellow "," purple "] // The value of child changes synchronouslyCopy the code

Advantages: good implementation of method sharing. Disadvantages: Because everything is shared, all attributes are shared, and all attributes change when an instance is modified.

Combination of inheritance

Features: the fusion of constructor inheritance and prototype chain inheritance, play to the advantages of both, therefore, it is a real sense of inheritance. How to do it: In a subclass, call is used to call the parent constructor and assign an instance of the parent function to the child function’s prototype.

function Flower(color){ this.color = color; } Flower.prototype.print = function() { console.log(this.color); } function Violate(color){ Flower.call(this,color) } Violate.prototype = new Flower() Violate.prototype.constructor = Status = New Status (' blue ') // Status = new Status (' blue ') status = New Status (' blue ') status = new Status (' blue ') status = new Status (' blue ') status = new Status (' blue ') status = new Status (' blue ') status = new Status The console. The log (child1. Print ()) / / blueCopy the code

Advantages: a good combination of constructor inheritance and prototype chain inheritance, play to the advantages of both, therefore, it is a real sense of inheritance. Cons: We still need to call the superclass constructor every time we instantiate a subclass, which can be a performance drain if the superclass constructor is more complex.

Parasitic inheritance

For composite inheritance, we don’t actually need to re-execute the superclass function, we just want to inherit the prototype of the superclass.

var obj = { color: 'red', print: function() { console.log(this.color); }}; var child1 = Object.create(obj); son1.print(); // red var child2 = Object.create(obj); son2.print(); // redCopy the code

Parasitic inheritance is essentially prototype chain inheritance, Object.create(obj); Parasitic inheritance does not require a constructor, but has the same advantages and disadvantages of prototype-chain inheritance, that is, it shares all properties and methods.

Parasitic combinatorial inheritance

Parasitic combinatorial inheritance is the combination of parasitic inheritance and combinatorial inheritance, which is the most perfect solution of inheritance and the realization principle of ES6 class syntax.

function Flower(color){ this.color = color; } Flower.prototype.print = function() { console.log(this.color); } function Violate(color){ Flower.call(this,color) } Violate.prototype = Object.create(Flower.prototype) Violate. The prototype. The constructor = Violate var child1 = new Violate (' purple ') console. The log (child1. Print ())/var/purple child1 = new Violate(' blue ') console.log(child1.print()) // BlueCopy the code

This code has only one difference, that is, the original Violate. Prototype = new Flower(); Violate. Prototype = object.create (flower.prototype);

As we mentioned earlier, the object. create method creates a new Object based on the Object passed in; After the new object is created, the value is assigned to Violate. Prototype, therefore, the status prototype finally points to the prototype object of the parent class, which has the same effect as new Flower(), but some performance is optimized compared with the combination inheritance.