JavaScript prototype and inheritance usage

Source: Internet
Author: User
Tags constructor function prototype inheritance types of functions

I. Function creation process

Before learning about the prototype chain, let's take a look at what a function does during creation. Let's take an example of an empty function:
Function (){};
When we declare such an empty function in the code, the essence of js parsing is (superficial understanding is needed ):
1. Create an object (with the constructor attribute and [[Prototype] attribute). According to ECMA, the [[Prototype] attribute is invisible and cannot be enumerated.
2. Create a function (with the name and prototype attributes), and then reference the created object through the prototype attribute.
3. Create variable A and assign the reference value of the function to variable.
As shown in the following figure:


(Note that the image is of the "reference" type)
Each function is created through the above process.

II. Constructor

So what is a constructor?

According to the definition of ECMA

Constructor is a function that creates and initializes the newly created object.
Constructor is a function used to create and initialize a new object at the same time.
What types of functions can be used to create and initialize new objects? The answer is: any function, including an empty function.
Therefore, the conclusion is that any function can be a constructor.

III. Prototype

According to the creation illustration of the empty function above, we know that each function is automatically added with the prototype attribute during creation. This is the prototype of the function, it can be seen from the figure that the essence is to reference an object (this object is now named as a prototype object ).
We can operate on the function's prototype object, which is similar to a common object! Together.
Around the empty function just created, add some code to the empty function this time:
Function (){
This. width = 10;
This. data = [1, 2, 3];
This. key = "this is ";
}
A. _ objectNum = 0; // defines the attributes of.
A. prototype. say = function () {// add attributes to A's prototype object
Alert ("hello world ");
}

7th ~ The nine lines of code add a say attribute to the prototype object of the function and reference an anonymous function. The following figure shows how to create a function:

(The gray background is the attribute added based on the null function)
In short, prototype is an attribute of a function. It is automatically added by the js compiler during function creation.
So what is the purpose of prototype?

First, understand the new operator as follows:

Var a1 = new;
Var a2 = new;

This is through the constructor to create an object. Why should we create an object like this instead of using var a1 =? This involves the specific steps of new. Here, the new operation can be divided into three steps (taking the creation of a1 as an example ):
1. Create an object and assign it to the variable a1: var a1 = {};
2. Point the [[Prototype] attribute of this object to the Prototype object of function A: a1. [[prototype] = A. Prototype
3. Call function A, point this to the object a1 created in 1, and initialize the object: A. apply (a1, arguments)
The structure diagram is as follows:

As shown in the figure, both a1 and a2 objects have an attribute that stores reference to the prototype object of function A. For these objects, some common methods can be found in the function prototype, saving memory space.
 
IV. Prototype chain

After learning about the new operator and Prototype, let's take a look at [Prototype]. And how can an object search attributes along this reference?
In the js world, each object has a [[Prototype] attribute by default, and its saved address constitutes the Prototype chain of the object, it is automatically added by the js compiler when an object is created. Its value is determined by the parameter on the right of the new operator: When var object1 =, [[Prototype] of object1 points to the Prototype Object of the object constructor, because var object1 = {}; is essentially equal to var Object = new Object (); (for the cause, refer to the above analysis process for new ).
When an object looks for a property, it first traverses its own property. If it does not, it will continue to look for the object referenced by [[Prototype, if no Prototype exists, continue to [[Prototype]. [[Prototype] referenced objects, and so on until [[Prototype]. .... [[Prototype] is undefined (the [[Prototype] of the Object is undefined)
As shown in the figure above:
// We want to obtain a1.fGetName
Alert (a1.fGetName); // output undefined
// 1. Traverse the a1 object itself
// The result a1 object does not have the fGetName attribute.
// 2. Find [[Prototype] of a1, that is, its corresponding object A. prototype, and traverse it at the same time.
// Result A. prototype does not have this attribute either.
// 3. Locate [[prototype] of the. Prototype Object and point to its corresponding Object. prototype
// The result Object. prototype does not have fGetName.
// 4. Try to find the [[prototype] attribute of Object. Prototype and return undefined. This is the value of a1.fGetName.
Simply put, you can use [[Prototype] of the object to save the reference to another object and use this reference to search for attributes. This is the Prototype chain.
 
V. Inheritance

With the concept of prototype chain, you can inherit it.
Function B (){};
At this time, B's prototype B. prototype is generated.
The prototype itself is an Object. Let's look at the data in it.
B. prototype is actually {constructor: B, [[Prototype]: Object. prototype}
Because prototype itself is an Object instance, its prototype chain points to the Object prototype.
B. prototype = A. prototype; // It is equivalent to pointing prototype of B to prototype of A. This only inherits the prototype method of A, and the custom square law of A does not inherit.
B. prototype. thisisb = "this is constructor B"; // this will change the prototype of.

But we just want to point the prototype chain of B to A. How can we implement it?
The first is to change the prototype link reference address.
B. prototype. _ proto _ = A. prototype;
ECMA does not have the _ proto _ method. This method is added by js interpreters such as ff and chrome, which is equivalent to [[Prototype] of EMCA. This is not a standard method, so how to use the standard method?
We know that the new operation actually points the prototype address block of the instance object to the prototype address block of the constructor, so we can perform this operation.
B. prototype = new ();
The result is:
Generate an instance of A and assign it to the prototype of B, that is, B. prototype is equivalent to {width: 10, data: [1, 2, 3], key: "this is A", [[Prototype]:. prototype}
In this way, the prototype of A is saved through the object attribute B. Prototype. [[prototype], forming the link of the Prototype.
However, note that the constructor of the object generated by B has changed. Because the constructor attribute does not exist in B, you can only find A. prototype from the prototype chain and read constructor:.
Var B = new B;
Console. log (B. constructor); // output
Therefore, we need to manually set bitself.
B. prototype. constructor = B;
// Now the Prototype of B is {width: 10, data: [1, 2, 3], key: "this is A", [[Prototype]:. prototype, constructor: B}
Console. log (B. constructor); // output B
// At the same time, B inherits the custom attributes width and name of A through the prototype.
Console. log (B. data); // output [1, 2, 3]
// The downside is that
B. data. push (4); // directly changes the prototype data array (reference)
Var c = new B;
Alert (c. data); // output [1, 2, 3, 4]
// In fact, all we want is the prototype chain. We want to define the custom attributes of A in B (instead of prototype)
// How to inherit?
// Since we do not want A custom attribute, we can try to filter it out.
// Create an empty function
Function F (){}
// Point the null function prototype to the prototype of constructor.
F. prototype = A. prototype;
// At this time, point the prototype chain of B. prototype to the prototype of F through the new operation.
B. prototype = new F;
// At this time, the Prototype of B is {[prototype]: F. Prototype}
// Here F. prototype is actually just an address reference
// However, the constructor of the instance created by B points to A. Therefore, the constructor attribute of B. prototype must be set here.
B. prototype. constructor = B;
// At this time, the Prototype of B is {constructor: B, [[prototype]: F. Prototype}
// In this way, B inherits the prototype of.

The figure below shows the prototype chain in red:

As a beginner's basic understanding, this article aims to better understand js Object-Oriented Information. Please correct us if you have any omissions.

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.