There are many kinds of inheritance in JS. This article only gives three common types of inheritance, hoping to provide some help for readers’ daily learning.

Prototype chain inheritance

Let’s look at an example to see what is a prototype chain inheritance

function SuperType() { / / the superclass
  this.superproerty = true
}
SuperType.prototype.getSuperValue = function () {
  return this.superproerty
}
function SubType() { / / subclass
  this.subproperty = false
}
SubType.prototype.getSuperValue = function () {
  return this.subproperty
}
SubType.prototype = new SuperType()
var instance = new SubType()
console.log(instance.getSuperValue()); 
Copy the code

Q: What is the final output? True or false? Answer: output true. Subtype.prototype = new SuperType() This line overwrites the SubType prototype object with an instance of SuperType, causing the SubType prototype object to find the SuperType prototype object.

In this example, SubType inherits from SuperType. SuperType is called a superclass, and inheritance is achieved by creating an instance of SuperType with new SuperType() and assigning the instance to the stereotype of SubType. The essence of the implementation is to override the prototype object of the subtype.

Stereotype chain: instance -> SubType stereotype -> SuperType stereotype -> Object stereotype

This is prototype-chain inheritance, making the prototype of a subclass equal to an instance of the superclass, implementing prototype-chain inheritance. Disadvantages:

  1. Instance properties of reference types defined in the superclass constructor become properties on the subclass stereotype and are shared by all instances of the subclass.
  2. When you create an instance of a subtype, you cannot pass arguments to the constructor of the superclass.

Constructor inheritance

Constructors are a great way to address the shortcomings of prototype chain inheritance

function SuperType() {
  this.colors = ['red'.'green'.'blue']}function SubType() {
  SuperType.call(this)}var instance = new SubType()
instance.colors.push('pink')
console.log(instance.colors); // [ 'red', 'green', 'blue', 'pink' ]
Copy the code

First, let’s explain the use of call() :

Call () lets you use methods that belong to another object.

Supertype.call (this) transfers the scope of SuperType to SubType, which is equivalent to copying the scope of SuperType to SubType. Does not affect the scope of SuperType itself.

function SuperType(color) {
  this.colors = ['red'.'green'.'blue']
  this.color = color
}
function SubType(color) {
  SuperType.call(this, color)
}
var instance = new SubType()
var instance4 = new SubType('yellow')
var instance2 = new SuperType()  // Scope is not affected
var instance3 = new SubType()
instance.colors.push('pink')
console.log(instance.colors); // [ 'red', 'green', 'blue', 'pink' ]
console.log(instance2.colors); // [ 'red', 'green', 'blue' ]
console.log(instance2.color); // Undefined instance instance4 does not affect the superclass scope
console.log(instance3.colors); // [ 'red', 'green', 'blue' ]
console.log(instance4.color); // yellow
Copy the code

You can see that in these four instances, the scope is not the same, and the passed arguments are not confused. This solves two disadvantages of the prototype chain. But it has its drawbacks:

  1. Non-essential properties may exist on instance objects of subclasses.
  2. Properties cannot be inherited from the superclass stereotype.

Combination of inheritance

Prototype chain inheritance + constructor inheritance directly in the example above

function SuperType(name) {
  this.name = name
  this.colors = ['red'.'green'.'blue']
}
SuperType.prototype.sayName = function () {
  console.log(this.name);
}

function SubType(name, age) {
  SuperType.call(this, name)  // Constructor inheritance
  this.age = age
}
SubType.prototype = new SuperType()  // Override the SubType stereotype object with an instance of SuperType
SubType.prototype.sayAge = function () {
  console.log(this.age);
}

var instance1 = new SubType('the old fish'.18)
instance1.colors.push('pink')
console.log(instance1.colors); // ['red', 'green', 'blue', 'pink']
instance1.sayName() / / an old fish
instance1.sayAge() / / 18

var instance2 = new SubType('there'.20)
console.log(instance2.colors); // [ 'red', 'green', 'blue' ]
instance2.sayName() / / shrimp
instance2.sayAge() / / 20
Copy the code

The above code takes advantage of both prototype chain inheritance and constructor inheritance, avoiding the disadvantages of both inheritance.

Subtype.prototype = new SuperType(); subtype.prototype.sayage = function () {console.log(this.age); } before this line of code, if the order is reversed, sayAge() will be overwritten, making sayAge() impossible to call.

Disadvantages:

  1. In any case, the superclass constructor is called twice.