1. Prototype chain inheritance

Those familiar with primitive chains should know that instances can inherit properties and methods from the constructor prototype chain. Suppose we have two constructors A and B, and we want the instance generated by the B constructor to inherit the properties and methods of the A constructor.

Thought 1: If the constructor B’s b.protoType points to the instance new A() generated by the constructor A, does B have access to the attributes of new A()? The A constructor also provides further access to properties and methods on the constructor A prototype chain.

code

			function A() {
				this.name = 'A'} // The parent's prototype method a.prototype.getName =function() {
				returnThis.name} // Subclassfunction B() {}

			B.prototype = new A()
			B.prototype.constructor = B

Copy the code

Think 2: B. constructor = B what does that mean? Constructor points to the original constructor (A). This looks strange because we know that the constructor property in the prototype of the constructor points to the constructor itself

What to do? Easy, we just need to redirect the constructr property in the prototype b.protoType of constructor B to B, perfect.

Disadvantages of prototype chain inheritance

1. Since all subclass instance stereotypes refer to the same parent class instance, modifying the parent class reference type variable of one subclass instance affects all instances

Note: This happens only when a variable attribute value of the parent constructor is a reference to the data type, not the base typeCopy the code

2, when creating a subclass instance, it cannot pass arguments to the parent class construction, that is, it does not implement the super() function


Constructor inheritance

Constructor inheritance, that is, execute the constructor of the parent class in the constructor of the child class and bind this to it. Let the parent class constructor attach member attributes and methods to this of the child class. This can not only avoid sharing a prototype instance between instances, but also pass parameters to the parent class constructor

function Parent(name) {
    this.name = [name]
}
Parent.prototype.getName = function() {
    return this.name
}
function Child() {
    Parent.call(this, 'zhangsan'// Execute the parent constructor and bind the subclass's this, // Test const child1 = new Child() const child2 = new Child() child1.name[0] ='foo'
console.log(child1.name)          // ['foo']
console.log(child2.name)          // ['zhangsan'] child2.getName() // error: getName() cannot be foundCopy the code

As you can see, the constructor inherits. In a subclass constructor, you can only inherit the attributes and methods of the parent constructor, but not the attributes and methods of the parent prototype

3. Combinatorial inheritance

Since both stereotype chain inheritance and constructor inheritance have complementary advantages and disadvantages, why not combine them so that we have composite inheritance that combines the two

function Parent(name) {
    this.name = [name]
}
Parent.prototype.getName = function() {
    return this.name
}
function Child() {// The constructor extends parent.call (this,'zhangsan'} / / prototype chain inheritance Child. The prototype = new Parent () the Child. The prototype. The constructor = Child / / testing const child1 Child () = new const child2 = new Child() child1.name[0] ='foo'
console.log(child1.name)          // ['foo']
console.log(child2.name)          // ['zhangsan']
child2.getName()                  // ['zhangsan']Copy the code

The constructor is executed twice each time a subclass instance is created.
Parent.call()and
new Parent()), although this does not affect inheritance from the parent class, it is not elegant to create instances of subclasses with two copies of the same properties and methods in the stereotype

4. Parasitic combination inheritance

To solve the problem of the constructor being executed twice, we change the point to superclass instance to point to the superclass prototype, minus one constructor execution

function Parent(name) {
    this.name = [name]
}
Parent.prototype.getName = function() {
    return this.name
}
function Child() {// The constructor extends parent.call (this,'zhangsan'Prototype = new Parent() child.prototype = object.create (Parent. Prototype) // Change 'point to Parent instance' to 'point to Parent prototype' Child. The prototype. The constructor = Child / / testing const Child Child () = new const parent = new parent () the Child. The getName () / / /'zhangsan'[parent.getName()] parent.getName()Copy the code



So far, we have completed the implementation of inheritance in ES5 environment. This inheritance method is called parasitic combinatorial inheritance, which is the most mature inheritance method at present. Babel’s transformation of ES6 inheritance also uses parasitic combinatorial inheritance

We review the implementation process: first prototype chain is the most easy to think of inheritance, by dividing the subclass instance prototype points to the parent class to inherit properties and methods of the parent, but the prototype chain of the defects in the inheritance the inheritance of the subclass instance reference type changes will affect all instances of the objects, and can’t to the parent class constructor arguments. Therefore, we introduced constructor inheritance, which gets the attributes and methods of the parent class by calling the parent constructor in the subclass constructor and passing in the subclass this. However, constructor inheritance also has a defect. Constructor inheritance cannot inherit the attributes and methods on the parent class prototype chain. So we integrated the advantages of two kinds of inheritance, put forward the combined inheritance, but also introduces a new combined hierarchy problems, it is time to create a subclass instances are performed twice the superclass constructor, we will through the subclass prototype points to the parent class instance to subclass prototype to shallow copy of the parent class prototype to solve this problem, the parasitic, finally realizes the modular inheritance