The things that JavaScript has to do with the central chain

Source: Internet
Author: User

Introduction

Inheritance is a very important concept in object-oriented languages, and many object-oriented languages support two ways of inheriting: interface inheritance and implementation inheritance. An interface inheritance system inherits only the method signature, and the implementation inherits the actual method. In ECMAScript the function has no signature, so ECMAScript cannot implement interface inheritance, only implement inheritance. So how to achieve the implementation of inheritance?? This is going to say that JS in the prototype chain.

Definition of the prototype chain

What is a prototype chain? This is a simple question, and the basic idea is to use a prototype to have a reference type inherit the properties and methods of another reference type.

Let's go back to the relationship between constructors, prototypes, and instances. Each constructor has a prototype object that contains a pointer to the constructor, and the instance contains an internal pointer to the prototype object. In the prototype object, the constructor is pointed to by prototype, and the prototype object is pointed to in the instance by __proto__, but the property is browser-sensitive, which is the property that some browsers add to the instance object, which is shown in ECMAScript as [[prototype]].

Now that we know that there is a pointer to the constructor in the prototype object, and now we have the prototype object equal to another instance of the type, the prototype object will contain a pointer to another prototype, and another prototype contains a pointer to another constructor. Join another prototype there are instances of another type, so this layer of progression constitutes the chain of examples and prototypes. This is the basic concept of the prototype chain.

My understanding : In my opinion, we can understand the prototype chain as a single-linked list, each prototype object contains a pointer to another prototype object, such a progressive link up, form a single linked list (but not that the structure of the prototype chain is a single-linked list, which is only easy to understand).

functionsupertype () { This. property =true;} Super.prototype.getSuperValue=function() {    return  This. property;}functionsubtype () { This. Subproperty =false;} Subtype.prototype=Newsupertype (); SubType.prototype.getSubValue=function() {    return  This. Subproperty;}varInstance =Newsubtype (); Console.log (Instance.getsupervalue ());//Output: True

As you can see, in the preceding code, the inheritance of the prototype chain is achieved by creating an instance of supertype and assigning the instance to the subtype prototype. The essence is to rewrite the prototype object and replace it with a new instance of the type. All the properties and methods that existed in an instance of supertype will exist in Subtype.prototype. The end result is this: instance points to Subtype's prototype, and subtype's prototype points to Supertype's prototype.

One thing to note is that instance.constructor now points not to subtype, but to supertype, because subtype's prototype points to another object Supertype prototype, The constructor attribute of this prototype object points to supertype.

Prototype search mechanism

Through the implementation of prototype chain, the prototype search mechanism is expanded. The prototype search mechanism, when accessing an instance property in read-write mode, first searches the instance for the attribute, and if it does not, continues to search for the prototype of the instance. In the case of a prototype chain inheritance, the search process continues upward along the prototype chain. First, the instance is searched, if there are any properties that need to be accessed in the instance, if not, the prototype of the instance will be searched, if there is a prototype attribute defined in the prototype, if there is no prototype that will be pointed up through the prototype chain, then the end of the link to the prototype chain will stop if no property or method is found.

The difference between prototype and __proto__

In the study of the prototype chain often do not understand the difference between prototype and __proto__, so the comparison of these two things to write a piece.

The origin of the __proto__ attribute : When a custom constructor is created, its prototype object only obtains the constructor property, and the other methods are inherited from Object, When a new instance is created using the constructor, the instance contains a prototype object that points to the constructor. In ECMAScript, this pointer is called [[Prototype]]. There is no standard way to access this pointer in the script. But Firefox, Safari, and chrome support an attribute __proto__ on each object, but in other implementations, this property is completely invisible to the script.

The default prototype

All reference types inherit object by default, and this inheritance is implemented through the prototype chain. 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 also why custom types will be happy with the default methods of ToString (), valueOf (), etc.

Prudent Definition method

1. The code to add a method to the prototype must be placed after the statement that replaced the prototype.

The following example:

        functionsupertype () { This. property =true; } SuperType.prototype.getSuperValue=function() {            return  This. property; }        functionsubtype () { This. Subpeoperty =false; } Subtype.prototype=Newsupertype (); //Add a new methodSubType.prototype.getSubValue =function() {            return  This. Subpeoperty; }                //overriding methods in super-typesSubType.prototype.getSuperValue =function() {            return false; }        varInstance =Newsubtype ();        Console.log (Instance.getsupervalue ()); //Output: False

In the above code, the overridden method masks the original method. When Getsupervalue () is called through an instance of subtype, the method is called, but the original method is called when Getsupervalue () is called through an instance of supertype.

2. When inheriting through a prototype chain, you cannot use object literals to create a prototype method.

This will rewrite the prototype chain. As shown in the following example:

            functionsupertype () { This. property =true; } SuperType.prototype.getSuperValue=function() {                return  This. property; }            functionsubtype () { This. Subproperty =false; } Subtype.prototype=Newsupertype (); Subtype.prototype={getsubvalue:function() {                    return  This. Subproperty; }, Someothermethod:function() {                    return false; }            }            varInstace =Newsubtype (); Console.log (Instace.getsupervalue ());

Output:

?

In the example above, we assign the supertype instance to the prototype, and then replace the award-winning prototype with an object literal, since the prototype now contains an object instance, not a supertype instance, and once the prototype chain has been cut off, Supertype and subtype have no relationship.

Problems with the prototype chain

1. We all know that a pointer to the heap memory is stored in an object of the reference type, so the prototype property that contains the reference type value is shared by all instances. Because the reference type in the prototype object is just a pointer, the pointer is copied when the object is instantiated, but the pointer point does not change. This is why you want to define the properties in the constructor, not in the prototype object. Look at the following code:

            functionsupertype () { This. colors = [' Red ', ' blue ', ' green ']; }            functionsubtype () {} Subtype.prototype=Newsupertype (); varInstace1 =Newsubtype (); Instace1.colors.push (' Black ');            Console.log (instace1.colors); varInstace2 =Newsubtype ();            Console.log (instace2.colors); //Output:            //["Red", "Blue", "green", "black"]            //["Red", "Blue", "green", "black"]

It is important to note that the prototype attribute of the primitive type value in JS is not:

            functionsupertype () { This. property =true; }            functionsubtype () {} Subtype.prototype=Newsupertype (); varInstace1 =Newsubtype (); Instace1.property=false;            Console.log (Instace1.property); varInstace2 =Newsubtype ();            Console.log (Instace2.property); //Output:            //false            //true

The reason is compared with the above example, we all know that the storage of the basic type value in JS is not through pointers.

2. When you create an instance of a subtype, you cannot pass parameters to the constructor of a super-type.

Based on these problems, in practice we will rarely use the prototype chain alone, as to how to better use the prototype chain in practice, the next blog I will explain in detail.

Above ~ ~

The things that JavaScript has to do with the central chain

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.