JS prototype and inheritance

Source: Internet
Author: User
Tags types of functions

I read "talking about JS object-oriented programming" a few days ago. At that time, I asked haoshen to findArticleIn some cases, it may be misleading (or different from ECMA). Later I flipped through ECMA and finally found the "standard ......
This article is suitable for beginners, especially those who are vague about the constructor, prototype, and prototype chain concepts. Let's take a look at the JS prototype (chain) step by step) how mysterious is it ......

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 A (){};

When weCodeTo declare such an empty function, 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 use the prototype attribute.ReferenceObject just created
3. Create variable A andReferenceAssign a value to variable
As shown in:

 

 

 

(Note:Reference"Type)
Each function is created through the above process.

Ii. Constructor

So what is a constructor?
According to the definition of ECMA

ConstructorIs a function thatCreatesAndInitializesThe 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:Any function can be a constructor.

Iii. Prototype

According to the preceding empty function creation illustration, we know that each function automatically adds the prototype attribute when it is created. This is the function'sPrototypeIt can be seen 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 A (){
This. Width = 10;
This. Data = [1, 2, 3];
This. Key ="This is";
}
A. _ objectnum = 0;// Define 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)
Simply putA 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 A;
VaR A2 =New A;

This is the way to create objects through constructors, so why should we create objects like this instead of directlyVaR A1 = {};What about it? 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 variable A1:VaR A1 = {};
2. Set the object's[[Prototype]Property pointing to functionAPrototype object:A1. [[prototype] = A. Prototype
3. Call function a andThisPoint to the object created in 1A1To initialize the object:A. Apply (A1, arguments)
The structure diagram is as follows:

 

 

 

 

 

 

 

 

 

 

 

 

 

We can see that both A1 and A2 have an attribute that storesAFor these objects, some common methods can be found in the prototype of the function, saving the 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 forms the prototype chain of the object, which is composed of the JS compiler in the objectCreatedIs automatically added when the value isNewThe parameter on the right side of the operator determines: When weVaR object1 = {};When,Object1Of[[Prototype]Point to the prototype object of the object constructor, becauseVaR object1 = {};Essentially equalVaR object = new object ();(For the reason, refer to the precedingNew).
When an object looks for an attribute, it first traverses its own attribute. If it does not, it continues to look[[Prototype]The referenced object. If no more, continue searching.[[Prototype]. [[prototype]Reference objects, and so on[[Prototype]... [[Prototype]IsUndefined(ObjectOf[[Prototype]YesUndefined)
As shown in:

// 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 putYou can use [[prototype] of an object to save a reference to another object and search for attributes through this reference. 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 the prototype of B to the 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 A ();

The result is:
Generate an instance of a and assign a value to the prototype of B, that isB. prototype is equivalent to {width: 10, data: [1, 2, 3], key: "This is a", [[prototype]: A. Prototype}
In this way, the prototype of a is passed throughB. Prototype. [[prototype]This object property is saved to form a prototype link.
However, note that the constructor of the object produced by B has changed. Because B does not have the constructor attribute, it can only be found from the prototype chain.A. Prototype, 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 changed the prototype data array (reference)
VaR C =New B;
Alert (C. Data );// Output [1, 2, 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:

 

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.