Inheritance in js

There are two ways of inheritance: interface inheritance and implementation inheritance. Interface inheritance only inherits method signatures, while implementation inheritance inherits the actual method.

Because the function has no signature, interface inheritance cannot be implemented in ECMAScript. ECMAScript only supports implementation of inheritance, and implementation of inheritance mainly depends on prototype chains.

Here are several js inheritances:

Back to the top

Prototype chain inheritance

The essence of prototype chain inheritance is to rewrite the prototype object and replace it with a new type of instance. The code is as follows:

function SuperType() {    this.property = true;
}

SuperType.prototype.getSuperValue = function() {    return this.property;
};function SubType() {    this.subproperty = false;
}// Inherited SuperTypeSubType.prototype = new SuperType();

SubType.prototype.getSubValue = function () {    return this.subproperty;
};var instance = new SubType();

console.log(instance.getSuperValue());  // true

You can see that instance invokes the parent getSuperVlue() method to implement inheritance.

The inheritance of prototype chains has the following problems:

  1. When a prototype containing a reference type value changes the reference type of the prototype, it all changes.

  2. When creating instances of subtypes, there is no way to pass parameters to supertype constructors without affecting all object instances.

The sample code is as follows:

function SuperType1() {    this.colors = ['red', 'blue', 'green'];
}function SubType1() {

}
SubType1.prototype = new SuperType1();var instance1 = new SubType1();
instance1.colors.push('black');
console.log(instance1.colors);  // [ 'red', 'blue', 'green', 'black' ]var instance2 = new SubType1();
console.log(instance2.colors);  // [ 'red', 'blue', 'green', 'black' ]

It can be found that the colors attributes of instance1 and instance2 are shared, which is a problem. At the same time, it can be seen that in a new method, if the value is passed, it can not pass to the parent.

Back to the top

Borrowing constructors

The principle is to call a supertype constructor inside a subtype constructor, because a function is simply an object that executes code in a particular environment, so you can get the methods and attributes of the parent.

The code is as follows:

function SuperType(name) {    this.name = name;
}function SubType(name) {    // It inherits SuperType and passes parameters.
    SuperType.call(this, name);    // Instance attributes
    this.age = 29;
}var instance = new SubType('Bob');

console.log(instance.name);  // Bobconsole.log(instance.age);  // 29

As you can see, calling constructor inheritance solves the problem of passing parameters to the parent type, but calling constructor also has its own problems:

  1. Methods are in constructors, and function reuse is not available.

  2. The methods defined in the prototype of a supertype are not visible to the subtypes.

The first problem is obvious. The explanation for the second problem is that since only one function is executed and no new object is generated, the method in the parent prototype is invisible to the subclass.

Back to the top

Combinatorial Inheritance

Because both prototype chain inheritance and borrowed constructor inheritance are defective, they will not be used alone in practice.

Combinatorial inheritance is a method of inheritance based on the advantages of both.

Its principle is to inherit prototype attributes and methods by using prototype chains, and to inherit instance attributes by borrowing constructors.

The code is as follows:

function SuperType(name) {    this.name = name;    this.colors = ['red', 'blue', 'green'];
}

SuperType.prototype.sayName = function() {
    console.log(this.name);
};function SubType(name, age) {    // Inheritance property
    SuperType.call(this, name);    this.age = age;
}// Inheritance method SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
    console.log(this.age);
};var instance1 = new SubType('Nicholas', 29);
instance1.colors.push('black');

console.log(instance1.colors);  // [ 'red', 'blue', 'green', 'black' ]instance1.sayName();  // Nicholasinstance1.sayAge(); // 29var instance2 = new SubType('Greg', 27);

console.log(instance2.colors);  // [ 'red', 'blue', 'green' ]instance2.sayName();  // Greginstance2.sayAge();  // 27

Combinatorial inheritance can solve the problems caused by the above two ways of inheritance, but it also has its own small problem, that is, it will call two supertype constructors, through analysis, we can know that one is when creating a prototype of subtype, the other is inside the subtype constructor.

Back to the top

Parasitic combinatorial inheritance

The principle of parasitic combinatorial inheritance is to inherit attributes by borrowing constructors and inherit methods by mixing prototype chains. The basic idea is that we do not need to call supertype constructors to specify sub-types of prototypes. All we need is a copy of supertype prototypes.

The code is as follows:

function object(o) {    function F() {}
    F.prototype = o;    return new F;
}function inheritPrototype(subType, superType) {    var prototype = object(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}function SuperType(name) {    this.name = name;    this.colors = ['red', 'blue', 'green'];
}

SuperType.prototype.sayName = function() {
  console.log(this.name);
};function SubType(name, age) {
    SuperType.call(this, name);    this.age = age;
}// The key inherit prototype (SubType, SuperType);

SubType.prototype.sayAge = function() {
    console.log(this.age);
};var instance = new SubType('Tianya', 23);
instance.sayName();
instance.sayAge();

Parasitic combinatorial inheritance only executes a supertype once when the constructor is called, which solves the minor problem of combinatorial inheritance.


Keywords: ECMAScript

Added by linux_pickle on Tue, 02 Jul 2019 00:09:44 +0300