ECMAScript only supports the implementation of inheritance, mainly relies on the prototype chain to achieve.
The way JavaScript implements inheritance:
- Class-Type Inheritance
- Constructor inheritance
- Combining inheritance
- Parasitic combined inheritance
1. Class-Type Inheritance
1 //class-Type inheritance2 //declaring a parent class3 functionAnimal (color) {4 This. Name = ' Animal ';5 This. Type = [' pig ', ' cat '];6 This. color =color;7 }8 //to add a common method to a parent class9Animal.prototype.greet =function(sound) {Ten Console.log (sound); One } A - //declaring a subclass - functionDog () { the This. Name = ' dog '; - } - - //class Inherits parent class (parent class instance as prototype object of subclass) +Dog.prototype =NewAnimal (' White '); - + //subclass instances inherit the properties and methods of the parent class A varDog1 =NewDog (); atConsole.log (Dog1.name);//Dog -Console.log (Dog1.type);//[' Pig ', ' cat '] -Dog1.greet (' Wangwangwang ');//' Wangwangwang ' - - //Bug 1: When you modify a subclass instance object to inherit from a property or method of a parent class, the newly created subclass instance is affected -Dog1.type.push (' Dog '); in varDOG2 =NewDog (); -Console.log (Dog2.type);//[' Pig ', ' cat ', ' dog '] to + //Flaw 2: Cannot initialize inherited properties for different instances, cannot pass arguments to the constructor of the parent class - //cannot assign different colors to different dog, all dog can be the same color theConsole.log (Dog1.color);//' White ' *Console.log (Dog2.color);//' White '
Rationale: When instantiating a class, the newly created object copies the properties and methods within the constructor of the parent class and initializes the prototype
__proto__
A prototype object that points to the parent class, which has properties and methods on the prototype object of the parent class.
two defects of class-type inheritance: (1) When a subclass instance object inherits from a property or method of a parent class, it affects the newly created subclass instance (2) Cannot initialize inherited properties for different instances, and cannot pass arguments to the constructor of the parent class
2. Constructor Inheritance
1 //Constructor Inheritance2 //declaring a parent class3 functionAnimal (color) {4 This. Name = ' Animal ';5 This. Type = [' pig ', ' cat '];6 This. color =color;7 }8 //to add a common method to a parent class9Animal.prototype.greet =function(sound) {Ten Console.log (sound); One } A - //declaring a subclass - functionDog (color, age) { theAnimal.apply ( This, arguments);//calling the parent class constructor inside a subclass constructor - This. Age =Age ; - } - + //subclass instances inherit the properties and methods of the parent class - varDog1 =NewDog (' White ', 1); + varDOG2 =NewDog (' Red ', 2); ADog1.type.push (' Dog '); at -Console.log (Dog1.color);//' White ' -Console.log (Dog1.type);//[' Pig ', ' cat ', ' dog '] -Console.log (Dog2.color);//' Red ' -Console.log (Dog2.type);//[' Pig ', ' cat '] - in //flaw: Unable to get a common method to the parent class, that is, the method of prototype binding through the prototype -Dog1.greet (' Wangwangwang ');//TypeError:dog1.greet is not a function toDog2.greet (' Wangwangwang ');//TypeError:dog2.greet is not a function
Constructor inheritance can avoid the defect of class inheritance, calling the parent class constructor inside the subclass constructor function. by using the Apply () and call () methods, you can change the scope of the function and execute the constructor on the newly created object.
So in the example above, we call this method in the dog subclass, which is to execute the variables of the dog subclass in the parent class, so that the class has the common properties and methods in the parent class.
constructor inheritance is also flawed , that is, we cannot get the common method of the parent class, that is, prototype
the method of binding through the prototype.
// flaw: Unable to get a common method to the parent class, that is, the method of prototype binding through the prototype // TypeError:dog1.greet is not a function // TypeError:dog2.greet is not a function
3. Combining Inheritance
Combining inheritance is a combination of class-and constructor-inheritance:
1 //combination Inheritance of class-type inheritance and constructor inheritance2 //declaring a parent class3 functionAnimal (color) {4 This. Name = ' Animal ';5 This. Type = [' pig ', ' cat '];6 This. color =color;7 }8 //to add a common method to a parent class9Animal.prototype.greet =function(sound) {Ten Console.log (sound); One } A - //declaring a subclass - functionDog (color, age) { theAnimal.apply ( This, arguments);//calling the parent class constructor inside a subclass constructor - This. Age =Age ; - } - + //class-Type inheritance -Dog.prototype =NewAnimal (); +Dog.prototype.constructor =Dog; A at //subclass instances inherit the properties and methods of the parent class - varDog1 =NewDog (' White ', 1); - varDOG2 =NewDog (' Red ', 2); -Dog1.type.push (' Dog '); - -Console.log (Dog1.color);//' White ' inConsole.log (Dog1.type);//[' Pig ', ' cat ', ' dog '] -Console.log (Dog2.color);//' Red ' toConsole.log (Dog2.type);//[' Pig ', ' cat '] + - //gets the common method to the parent class theDog1.greet ("Wang");//' Wang ' *Dog2.greet ("Miao");//' Miao ' $ Panax Notoginseng //defect: Two times the parent class constructor was called -Dog.prototype =NewAnimal ();//First time Call theAnimal.apply ( This, arguments);//Second Call
In the example above, we execute the parent class constructor in the subclass constructor, instantiate the parent class on the subclass prototype, this is the combination of inheritance, you can see that it combines the advantages of class-type inheritance and constructor inheritance, and removes the flaw. Combining inheritance is the most common way of inheriting in JavaScript. You might wonder why combined inheritance can remove a reference flaw in class inheritance? In fact, this is because
原型链
To determine, because the JavaScript engine accesses the object's properties, it looks in the object itself, if not found, will go to the prototype chain to find, if found, the return value, if not found in the entire prototype chain, the property is returned undefined. That is, the type of reference we are accessing (such as the type above) is actually
apply
Copied to the subclass, so no sharing occurs.
the drawback of combinatorial inheritance is that it calls the constructors of the parent class two times.
// defect: Two times the parent class constructor was called New // First time Call Animal.apply (this// second call
4. Parasitic combined inheritance
The part of parasitic combined inheritance hardening is to reduce the redundant calls to the parent class's constructor on the basis of the combined inheritance. As the most used is still the combination of inheritance, parasitic composite inheritance does not do in-depth exploration, there is interest can refer to JS elevation P172.
Summarize
JavaScript implements inheritance primarily through the prototype chain . The construction of a prototype chain is accomplished by assigning an instance of one type to the prototype of another constructor . In this way, subtypes have access to all properties and methods of the parent type, which is similar to class-based inheritance.
The problem object instance of the prototype chain shares all inherited methods and properties, and when modifying a subclass instance object inherits from a property or method of the parent class, it affects the newly created subclass instance, so it is not appropriate to use it alone.
The technique for solving this problem is to borrow a constructor, that is, to call the parent type constructor inside the sub-type constructor. This allows each instance to have its own properties, while also guaranteeing that only the constructor pattern is used to define the type. However, the result of using this method is that you cannot get the common method of the parent class, that is, prototype
the method of binding through the prototype.
The most used integration pattern is the combination of inheritance, which combines the advantages of class inheritance and constructor inheritance, while excluding defects. Even if you inherit shared properties and methods with the prototype chain, you inherit the instance properties by borrowing the constructor.
Reference: How JavaScript implements Inheritance
How JavaScript implements inheritance and the pros and cons of each