JavaScript inheritance (a) prototype chain inheritance

Source: Internet
Author: User

Inherited

Inheritance is one of the most talked about concepts in oo language. Many OO languages support two ways of inheriting: interface inheritance and implementation inheritance .

Interface inheritance inherits only the method signature, while implementing inheritance inherits the actual method.

As mentioned earlier, because the function is not signed, interface inheritance cannot be implemented in ECMAScript. ECMAScript only supports implementation of inheritance, and its implementation is mainly based on the prototype chain to achieve.

1. Prototype chainThe concept of prototype chain is described in ECMAScript, and the prototype chain is used as the main method to implement inheritance.The basic idea is to use a prototype to let one reference type inherit the properties and methods of another reference type.Briefly review the relationship of constructors, prototypes, and instances: each constructor has a prototype object, and the prototype object contains a pointer to the constructor, and the instance contains an internal pointer to the prototype object.So what happens if we let the prototype object be equal to another instance of the type?Obviously, the prototype object at this point will contain a pointer to another prototype, and a pointer to another constructor is also included in the other prototype.If another prototype is another type of example, then the relationship is still established, so that the level of progression, constitutes an example and prototype chain.This is the basic concept of the so-called prototype chain.

There is a basic pattern for implementing the prototype chain, which is roughly the following code.

function supertype () {  this.property = true;} SuperType.prototype.getSuperValue = function () {  return this.property;}; function subtype () {  This.subproperty = false; }//Inherits Supertype Subtype.prototype = new Supertype (); SubType.prototype.getSubValue = function () {  
The code above defines two types: Supertype and subtype. Each type has one property and one method. The main difference is that subtype inherits supertype, and inheritance is done by creating an instance of supertype and assigning that instance to Subtype.prototype. The essence of implementation is to rewrite the prototype object and replace it with an instance of a new type. In other words, all the properties and methods that existed in an instance of supertype now exist in Subtype.prototype. After we have established the inheritance relationship, we add a method to Subtype.prototype, which adds a new method based on inheriting the properties and methods of Supertype. The examples in this example and the relationship between constructors and prototypes are shown in 6-4.

In the above code, instead of using the prototype provided by the subtype default, we have replaced it with a new prototype, which is an example of supertype. As a result, the new prototype not only has all the properties and methods as an instance of Supertype, but also has a pointer inside it, pointing to the Supertype prototype. The end result is this: instance points to Subtype's prototype, and subtype's prototype points to Supertype's prototype. The Getsupervalue () method is still in Supertype.prototype, but the property is in Subtype.prototype. This is because the property is an instance attribute, and Getsupervalue () is a prototype method. Since Subtype.prototype is now an instance of Supertype, the property is of course in that instance. Also, be aware that Instance.constructor is now pointing to supertype, which is because the constructor in the original Subtype.prototype was rewritten.

When an instance property is accessed in read mode, the attribute is first searched in the instance. If the property is not found, the prototype of the instance will continue to be searched. In the case of inheritance through the prototype chain, the search process continues upward along the prototype chain. Take the example above, call Instance.getsupervalue () will go through three search steps: 1) Search instance, 2) search subtype.prototype;3) Search Supertype.prototype, the last step to find the method. In the case where a property or method is not found, the search process is always going to stop at the end of the prototype chain by a loop.

1. Don't forget the default prototype

In fact, the prototype chain shown in the previous example is less than a loop. We know that all reference types inherit object by default, and this inheritance is implemented through the prototype chain. Remember that the default prototype for all functions is an instance of object, so the default prototype will contain an internal pointer to Object.prototype. This is why all custom types inherit the root cause of the default methods, such as ToString (), ValueOf (). Therefore, we say that the prototype chain shown in the example above should also include another inheritance hierarchy. The complete prototype chain in this example is shown in Figure 6-5.


In a word, subtype inherits the Supertype, and Supertype inherits the object. When you call Instance.tostring (), you actually call the method that you saved in Object.prototype.

2. Determining the relationship between prototypes and instancesThere are two ways to determine the relationship between a prototype and an instance. The first is to use the instanceof operator, as long as the operator is used to test the constructor in the instance and the prototype chain, and the result returns TRUE. This is illustrated in the following lines of code.
Alert (instance instanceof Object); Truealert (instance instanceof supertype); Truealert (instance instanceof subtype); True
Because of the relationship of the prototype chain, we can say that instance is an instance of any of the types in object, Supertype, or subtype. Therefore, the result of testing these three constructors returns true.
The second way is to use the isPrototypeOf () method. Similarly, the isprototypeof () method also returns true as long as the prototype in the prototype chain is a prototype of the instance derived from the prototype chain, as shown below.
Alert (Object.prototype.isPrototypeOf (instance)); Truealert (SuperType.prototype.isPrototypeOf (instance)); Truealert (SubType.prototype.isPrototypeOf (instance)); True
3. Carefully define the methodSubtypes sometimes need to rewrite a method in a superclass, or you need to add a method that does not exist in the super type. However, the code that adds a method to the prototype must be placed after the statement that replaced the prototype. Take a look at the following example.
function supertype () {this.property = true;} SuperType.prototype.getSuperValue = function () {return this.property;}; Function subtype () {this.subproperty = false;} Inherited supertypesubtype.prototype = new supertype ();//Add a new Method <strong>subtype.prototype.getsubvalue = function () { return this.subproperty;}; </strong>//override method in Super-type <strong>subtype.prototype.getsupervalue = function () {return false;}; </strong>var instance = new subtype (); alert (Instance.getsupervalue ()); False
In the above code, the bold part is the definition of two methods. The first method, Getsubvalue (), is added to the subtype. The second method, Getsupervalue (), is a method that already exists in the prototype chain, but overriding this method will block the original method. In other words, when calling Getsupervalue () from an instance of subtype, this redefined method is called, but when Getsupervalue () is called through an instance of Supertype, the original method continues to be called. It is important to note that these two methods must be defined after replacing the prototype with an instance of supertype. One more thing to remind, that is, when you implement inheritance through a prototype chain, you cannot use object literals to create a prototype method。 Because doing so will rewrite the prototype chain, as shown in the following example.
function supertype () {this.property = true;} SuperType.prototype.getSuperValue = function () {return this.property;}; Function subtype () {this.subproperty = false;} Inherited supertypesubtype.prototype = new supertype ();//using the literal to add a new method causes the previous line of code to be invalid Subtype.prototype = {Getsubvalue:function ( {return this.subproperty;},someothermethod:function () {return false;}}; var instance = new subtype (); alert (Instance.getsupervalue ()); error!

The code above shows the problem that has just been assigned to the prototype, and then replaced the prototype with an object literal. supertype. Since the prototype now contains an instance of object, not an instance of supertype, we envision that the prototype chain has been cut off between--subtype and Supertype.
4. Problems with the prototype chainAlthough the prototype chain is powerful, it can be used to implement inheritance, but it also has some problems. Among them, the most important problem comes from prototypes that contain reference type values. As you can remember, we described earlier that the prototype property that contains the reference type value is shared by all instances, and that is why the attribute is defined in the constructor, not in the prototype object. When you implement inheritance through a prototype, the prototype will actually become an instance of another type. As a result, the original instance attributes have naturally become the archetypal attributes of the present. The following code can be used to illustrate this problem.

function supertype () {this.colors = ["Red", "Blue", "green"];} Function subtype () {}//Inherits Supertypesubtype.prototype = new Supertype (); var Instance1 = new subtype (); Instance1.colors.push ("Black"); alert (instance1.colors); "Red,blue,green,black" var instance2 = new subtype (); alert (instance2.colors); "Red,blue,green,black"
The Supertype constructor In this example defines a colors property that contains an array (reference type value). Each instance of Supertype will have its own colors property that contains its own array. When subtype inherits Supertype through the prototype chain, Subtype.prototype becomes an instance of supertype, so it also has its own colors attribute-- It's just like creating a SubType.prototype.colors property specifically. But what is the result? As a result, all instances of subtype share this colors property. This has been amply confirmed by the fact that our changes to instance1.colors can be reflected through instance2.colors. The second problem with the prototype chain is that when you create an instance of a subtype, you cannot pass parameters to the super-type constructor. In fact, it should be said that there is no way to pass parameters to a super-type constructor without affecting all object instances. With this in mind, and in addition to the problems that have been discussed earlier in the prototype that contain reference type values, it is seldom used in practice to use the prototype chain alone.

JavaScript Inheritance (one) of the prototype chain inheritance

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.