One of the characteristics of object-oriented is inheritance. Most object-oriented programming languages support two inheritance Methods: interface inheritance and implementation inheritance. Interface inheritance only inherits the method signature, while implementation inheritance inherits the actual method. Because functions in JavaScript do not have signatures, interface inheritance cannot be implemented. In JavaScript, the inheritance is mainly implemented through the prototype chain. One of the characteristics of object-oriented is inheritance. Most object-oriented programming languages support two inheritance Methods: interface inheritance and implementation inheritance. Interface inheritance only inherits the method signature, while implementation inheritance inherits the actual method. Because functions in JavaScript do not have signatures, interface inheritance cannot be implemented. In JavaScript, the inheritance is mainly implemented through the prototype chain.
Implement inheritance based on prototype chain
The basic idea of inheritance based on prototype chain is to use prototype to let one reference type inherit the attributes and methods of another reference type. We have introduced the relationship between the prototype, constructor and object instance, and analyzed their memory model structure in detail. The following example is used to analyze how JavaScript implements inheritance based on prototype chain.
// Create the Parent class function Parent () {this. parentValue = "Parent";} // Add the Parent Method to the Parent class prototype. prototype. showParentValue = function () {alert (this. parentValue);} // create a subclass function Child () {this. childValue = "Child";} // implement inheritance, let the prototype chain of Child point to the Parent object Child. prototype = new Parent (); // Add the Child Method to the prototype of the subclass. prototype. showChildValue = function () {alert (this. childValue);} // create the subclass object var c = new Child (); // The subclass object calls the method c inherited from the parent class. showParentValue (); // The subclass object calls its own method c. showChildValue ();
In the above Code, we first created a Parent class Parent and added the showParentValue method to its prototype.
Then we create a Child subclass and inherit it by pointing the prototype chain of the subclass to the parent class.
/** Key code for inheritance **/Child. prototype = new Parent ();
Then add the showChildValue Method to the prototype chain of the subclass. Then, a subclass object is created. In this case, the subclass Object c can call both its own method and the method inherited from the parent class.
After the above code is executed, the memory model of the Child class and the parent class is shown in:
The default prototype of all functions is Object. Therefore, the default prototype contains an internal pointer pointing to Object. prototype. The built-in hasOwnProperty, isPrototypeOf, propertyEmunerable, toLocaleString, toString, and valueOf methods are available in Object. prototype. Therefore, all custom types inherit these methods.
Considerations when using prototype chain for inheritance
When using prototype chain for inheritance, pay attention to the following issues:
For the first point, let's look at the following example:
Function Parent () {this. parentValue = "Parent";} Parent. prototype. showParentValue = function () {alert (this. parentValue);} function Child () {this. childValue = "Child";} // implement inheritance to point the Child prototype chain to the Parent object Child. prototype = new Parent (); // The following Operation overwrites the Child prototype. prototype = {showChildValue: function () {alert (this. value );}}
In the above Code, we create a parent class and a subclass respectively, and let the prototype of the subclass point to the parent class object to implement inheritance. But after that, we use Child. prototype = {...} this method overwrites the prototype of the subclass. As we have already mentioned in the article of prototype rewriting, the prototype rewriting actually enables the prototype of the subclass to point to a new subclass prototype, there is no association between the new subclass prototype and the parent class, so there is no inheritance relationship between the subclass and the parent class.
I also have a good understanding of the second point. Let's look at an example:
Function Parent () {this. parentValue = "Parent";} Parent. prototype. showParentValue = function () {alert (this. parentValue);} function Child () {this. childValue = "Child";} // Add the Child Method to the prototype for subclass before implementation inheritance. prototype. showChildValue = function () {alert (this. childValue);} // implement inheritance to point the Child prototype chain to the Parent object Child. prototype = new Parent ();
In the above Code, we created parent classes and child classes respectively. After creating a subclass, immediately add a method to the subclass in the prototype, and then let the Child prototype chain point to the Parent object to implement inheritance.
After inheritance is implemented, the subclass points to the new subclass prototype, and the method added previously is placed in the original prototype (the red area in the memory model diagram ), therefore, after implementation inheritance, the subclass object will no longer have this method, because the original prototype does not work now.
Coverage of methods and disadvantages of prototype chain inheritance
If we need to implement the subclass method to override the parent class method, we only need to add a method with the same name as the parent class in the subclass prototype.
/** Override the showParentValue method in the Parent class **/Child. prototype. showParentValue = function () {alert ("Override Parent method ");}
Although prototype chain is powerful and can be inherited, prototype chain also has some disadvantages. The main disadvantages of prototype chain inheritance are:
1. The biggest disadvantage of using prototype chain for inheritance is that the constructor of the parent class cannot be called from the subclass, so that attributes of the subclass cannot be assigned to the parent class.
2. If a property of the reference type exists in the parent class, the reference type is added to the prototype of the subclass. After the reference is modified for the first object, the reference of other objects will also be modified.
The prototype chain and prototype have the same problem when processing the value of the reference type. When introducing the prototype, we once gave an example of using the reference type. This problem also occurs when prototype chain is used. Let's look at the following example:
// Create the Parent class function Parent () {this. parentValue = "Parent"; // property of the reference type this. friends = ['on', 'ada '];} // Add the Parent Method to the Parent class prototype. prototype. showParentValue = function () {console.info (this. name + "[" + this. friends + "]");} // creates a subclass function Child () {this. childValue = "Child";} // implement inheritance, let the prototype chain of Child point to the Parent object Child. prototype = new Parent (); // Add the Child Method to the prototype of the subclass. prototype. showChildValue = function () {console.info (this. name + "[" + this. friends + "]");} // create a subclass object var person1 = new Child (); person1.name = "Jack"; person1.friends. push ('Tom '); var person2 = new Child (); person2.name = "John"; console.info (person2.friends );
In the code above, there is an array object attribute friends of the reference type in the parent class. After the subclass is inherited, The subclass object person1 adds a new friend to its friends, new friends are added to the prototype of the parent class, so all new objects created after this will have a new friend "Tom ". This is a problem with the reference type attribute.
The above is JavaScript object-oriented-implement inheritance based on prototype chain. For more information, see PHP Chinese website (www.php1.cn )!