In-depth exploration of JavaScript prototype

Source: Internet
Author: User

1. What is prototype?

The prototype attribute of the object in Javascript, which can return the reference of the Object Type prototype. This is an equivalent

To understand the concept of object type and prototype.

As we mentioned above, the class of an object and the instance of an object are in a "CREATE" relationship,

Therefore, we regard "class" as the modeling of object features, and the object as the embodiment of class features, or

(Class) is a type of the object ). For example, in the previous example, the P1 and P2 types are both point,

In JavaScript, this can be verified through the instanceof OPERATOR:

P1 instanceof point

P2 instanceof point

However, point is not the only type of P1 and P2, because P1 and P2 are both objects, so obejct is also

Because the object is a class that is more generalized than the point, we say that there is

Derivative relationships. We will know later that this relationship is called "inheritance", which is also a generalization relationship between objects.

Is an indispensable basic relationship in object-oriented systems.

In the Object-Oriented field, instances and types are not the only one pair of descriptive abstract relationships. In JavaScript,

Another important abstract relationship is type and prototype ). This relationship is a higher level of extraction.

It Exactly forms a three-tier chain with the abstract relationship between types and instances.

In real life, we often say that something is created based on another thing. These two items are acceptable.

Is of the same type or different types. The idiom "depends on the gourd painting". The gourd here is the prototype, and the gourd is

Type, which is represented by the prototype in Javascript as "handler. Prototype = a gourd" or

"Pipeline. Prototype = new hoist ()".

To thoroughly understand the prototype, you can study a design pattern of prototype pattern.

The core is to use a prototype instance to specify the type of the object to be created, and create a new object by copying the prototype.

The prototype of JavaScript is similar to this method.

For more information about prototype pattern, see design patterns.

Is the scope of this article.

Note that the relationship between the same type and the instance is different. The relationship between the prototype and the instance requires that one type can only be at one time.

There is a prototype (and an instance can obviously have multiple types at a time ). For JavaScript, this restriction has two meanings. The first is that each specific JavaScript type has only one prototype. By default, this prototype is an object (note that it is not of the Object Type !). Second, the object type must be a type chain that satisfies the prototype relationship. For example, P1 belongs to the type of point and object, while an object is a prototype of point. If an object belongs to the following types: classa, classb, classc, and object, the four classes must constitute a complete prototype chain.

Interestingly, JavaScript does not specify a prototype for a prototype (this is a very colloquial

So it can be any type, usually an object. In this way, the object-type-prototype (object) may Structure

Into a ring structure, or other interesting topology, these structures bring a wide variety of JavaScript

Usage, some of which are both clever and aesthetic. The following section describes how to use prototype.

 

2. Prototype usage skills

 

Before learning how to use prototype, first understand the features of prototype. First, JavaScript

A prototype attribute is provided for each type. to direct this attribute to an object, the object

It becomes a "prototype" of this type, which means that all objects created by this type have the characteristics of this prototype.

In addition, the JavaScript Object is dynamic, and the prototype is no exception. add or remove attributes to or from prototype

To change the prototype, this change will directly apply to all objects created by this prototype, for example:

<SCRIPT>

Function Point (x, y ){

This. x = X;

This. Y = y;

}

VaR p1 = new point (1, 2 );

VaR P2 = new point (3, 4 );

Point. Prototype. z = 0; // attributes are dynamically added to the prototype of the point.

Alert (p1.z );

Alert (p2.z); // all objects created for the point type at the same time

</SCRIPT>

Result: The first time is 0. The second time is 0.

If a property named a is added to the prototype of an object, the object itself has another property named

When a accesses the object's property A, the object's property overwrites the prototype property,

The prototype property does not disappear. When you use the delete operator to delete attribute a of the object itself, the prototype property of the object

The visibility is restored. With this feature, you can set the default value for the object property, for example:

<SCRIPT>

Function Point (x, y ){

If (x) This. x = X;

If (y) This. Y = y;

}

Point. Prototype. x = 0;

Point. Prototype. Y = 0;

VaR p1 = new point;

VaR P2 = new point (1, 2 );

Alert (p1.x + "" + p1.y );

Alert (p1.x + "" + p1.y );

</SCRIPT>

Result: First Time: 0 0 second time: 0 0

In the above example, the default value (0, 0) is set for the point object through prototype, so the value of P1 is (0, 0), p2

The value is (1, 2). You can use Delete p2.x, delete p2.y; to restore the P2 value to (0, 0 ). Below is

More interesting example:

<SCRIPT>

Function classa (){

This. A = 100;

This. B = 200;

This. c = 300;

This. Reset = function (){

For (VAR each in this ){

Delete this [Each];

}

}

}

Classa. Prototype = new classa ();

VaR A = new classa ();

Alert (A. );

A. A * = 2;

A. B * = 2;

A. C * = 2;

Alert (A. );

Alert (A. B );

Alert (A. C );

A. Reset (); // call the reset method to restore the value of a to the default value.

Alert (A. );

Alert (A. B );

Alert (A. C );

</SCRIPT>

Prototype can also be used to set a read-only getter for the object attribute to avoid rewriting. Lower

Surface is an example:

<SCRIPT>

Function Point (x, y ){

If (x) This. x = X;

If (y) This. Y = y;

}

Point. Prototype. x = 0;

Point. Prototype. Y = 0;

Function linesegment (P1, P2 ){

// Private member

VaR m_firstpoint = p1;

VaR m_lastpoint = P2;

VaR m_width = {

Valueof: function () {return math. Abs (p1.x-p2.x )},

Tostring: function () {return math. Abs (p1.x-p2.x )}

}

VaR m_height = {

Valueof: function () {return math. Abs (p1.y-p2.y )},

Tostring: function () {return math. Abs (p1.y-p2.y )}

}

// Getter

This. getfirstpoint = function (){

Return m_firstpoint;

}

This. getlastpoint = function (){

Return m_lastpoint;

}

This. Length = {

Valueof: function (){

Return math. SQRT (m_width * m_width + m_height * m_height)

},

Tostring: function (){

Return math. SQRT (m_width * m_width + m_height * m_height)

}

}

}

VaR p1 = new point;

VaR P2 = new point (2, 3 );

VaR line1 = new linesegment (P1, P2 );

VaR Lp = line1.getfirstpoint ();

LP. x = 100; // accidentally rewrite the LP value, destroys the original LP value and cannot be recovered.

Alert (line1.getfirstpoint (). X );

Alert (line1.length); // even line1.lenght has changed

</SCRIPT>

Rewrite this. getfirstpoint () as follows:

This. getfirstpoint = function (){

Function getter (){};

Getter. Prototype = m_firstpoint;

Return new getter ();

}

This problem can be avoided, ensuring the read-only attribute of m_firstpoint.

<SCRIPT>

Function Point (x, y ){

If (x) This. x = X;

If (y) This. Y = y;

}

Point. Prototype. x = 0;

Point. Prototype. Y = 0;

Function linesegment (P1, P2 ){

// Private member

VaR m_firstpoint = p1;

VaR m_lastpoint = P2;

VaR m_width = {

Valueof: function (){

Return math. Abs (p1.x-p2.x)

},

Tostring: function (){

Return math. Abs (p1.x-p2.x)

}

}

VaR m_height = {

Valueof: function (){

Return math. Abs (p1.y-p2.y)

},

Tostring: function (){

Return math. Abs (p1.y-p2.y)

}

}

// Getter

This. getfirstpoint = function (){

Function getter (){};

Getter. Prototype = m_firstpoint;

Return new getter ();

}

This. getlastpoint = function (){

Function getter (){};

Getter. Prototype = m_lastpoint;

Return new getter ();

}

This. Length = {

Valueof: function (){

Return math. SQRT (m_width * m_width + m_height * m_height)

},

Tostring: function (){

Return math. SQRT (m_width * m_width + m_height * m_height)

}

}

}

VaR p1 = new point;

VaR P2 = new point (2, 3 );

VaR line1 = new linesegment (P1, P2 );

VaR Lp = line1.getfirstpoint ();

// Line1.getfirstpoint () returns a getter object, but getter. prototype = m_firstpoint; m_firstpoint is a prototype object of the getter type, which is equivalent to a base class Object of the getter type. Therefore, the getter instance object can use all members of the m_firstpoint. Example: 1p. X = 100; 1 P is actually a getter object, but 1 p contains members of the m_firstpoint object.

 

LP. x = 100; // The LP value is accidentally rewritten, but the original value is not damaged.

Alert (line1.getfirstpoint (). X );

Alert (line1.length); // line1.lenght does not change

</SCRIPT>

In fact, setting an object as a prototype is equivalent to creating an object by instantiating this type.

A read-only copy that changes the copy at any time does not affect the original object, but changes the original object,

This will affect the copy, unless the changed attributes have been overwritten by the copy's own attributes with the same name. Use the delete operation

If you delete an attribute with the same name, the visibility of the prototype attribute can be restored. Here is another example:

M_firstpoint Original Version

X = 0;

Object

M_firstpoint copy

X = 0;

Object

 

When you create an instance of the type, the copy (prototype = Object) object is copied to the instance object. (The default value of prototype is the object.) When a property or method is dynamically added through prototype, the attribute or method is added (

Prototype = object.

 

<SCRIPT>

Function polygon (){

VaR m_points = [];

M_points = array. Apply (m_points, arguments );

Function getter (){};

Getter. Prototype = m_points [0];

This. firstpoint = new getter ();

This. Length = {

Valueof: function (){

Return m_points.length

},

Tostring: function (){

Return m_points.length

}

}

This. Add = function (){

M_points.push.apply (m_points, arguments );

}

This. getpoint = function (idx ){

Return m_points [idx];

}

This. setpoint = function (idx, point ){

If (m_points [idx] = NULL ){

M_points [idx] = point;

} Else {

M_points [idx]. x = point. X;

M_points [idx]. Y = point. Y;

}

}

}

VaR P = new polygon ({X: 1, Y: 2}, {X: 2, Y: 4}, {X: 2, Y: 6 });

Alert (P. Length );

Alert (P. firstpoint. X );

Alert (P. firstpoint. y );

P. firstpoint. x = 100; // The value is accidentally written.

Alert (P. getpoint (0). X); // The actual private member is not affected.

Delete P. firstpoint. X; // restore

Alert (P. firstpoint. X );

P. setpoint (0, {X: 3, Y: 4}); // rewrite the actual private member through setter

Alert (P. firstpoint. X); // The value of getter is changed.

Alert (P. getpoint (0). X );

</SCRIPT>

Note: The preceding example shows how to use prototype to quickly create multiple copies of an object.

Using prototype to create a large number of complex objects is much faster than using any other method to copy objects. Notes,

Using an object as the prototype to create a large number of new objects is the essence of prototype pattern.

The following is an example:

<SCRIPT>

VaR p1 = new point (1, 2 );

VaR points = [];

VaR pointprototype = function (){};

Pointprototype. Prototype = p1;

For (VAR I = 0; I <10000; I ++ ){

Points [I] = new pointprototype ();

// Because the pointprototype constructor is an empty function, its constructor is more efficient than the direct constructor/P1.

This is much faster.

}

</SCRIPT>

In addition to the usage techniques mentioned above, prototype has its unique features and other functions,

Perhaps the most widely used and widely known is to use it to simulate inheritance, which will be discussed in the next section.

3. Prototype

The role of prototype has been discussed above. Now we can reveal the essence of prototype through laws.

We say that prototype acts like a static field in C ++ and adds an attribute as a prototype attribute,

This attribute will be shared by all instances created for this type, but this type of sharing is read-only. In any instance

You can overwrite this property with the same name without changing it. In other words, when an object reads an attribute,

Always check the Attribute Table of the domain. If this attribute exists, this attribute will be returned; otherwise, prototype will be read.

Returned protoype attribute. In addition, JavaScript allows the protoype field to reference any type of object,

Therefore, if this attribute is still not found for reading protoype fields, JavaScript will Recursively search

The prototype field directs to the prototype field of the object until the prototype field of the object is itself or appears

So far, we can use the following figure to describe the relationship between prototype and object instance:

Search priority:

1. attributes of this instance
2. Prototype attributes
3. Properties of the object to which the prototype field points
// Todo:

4. value and limitations of Prototype

From the above analysis, we understand prototype. It can be used as a prototype to create a large number

This is the true meaning of prototype and its value. We will see that the prototype

This feature can be used to simulate Object Inheritance, but you must know that prototype is used to simulate inheritance.

But it is definitely not the core. In other words, JavaScript supports prototype,

It is definitely not just used to implement its object inheritance. Even if prototype inheritance is absent, the prototype of JavaScript

The mechanism is still very useful.

Prototype only uses objects as the prototype to build copies for the type, so it also has great limitations. First,

In the prototype field of the type, it is not a copy of the value, but a copy of the reference.

". Changing the property value of a property of the reference type on a prototype (which is equivalent to the following explanation: p) will completely affect (in all instances created with this type, all references the same prototype object. Changes to prototype in any instance will affect all instances. Note the copy concept mentioned above. For example: var obj1 = new objectx (); obj2.prototype = obj1; according to the copy concept, it is essentially to create an independent copy of obj1 and assign it to the prototype of obj2) -- explains the example below

Every instance created for this type. Sometimes this is exactly what we need (for example, changes to all objects of a certain type)

The default value), but sometimes this is not what we want (for example, in class inheritance), the following example is given:

<SCRIPT>

Function classa (){

This. A = [];

}

Function classb (){

This. B = function (){};

}

VaR c = new classa ();

Classb. Prototype = C;

Objb1 = new classb ();

VaR objb2 = new classb ();

Objb1.a. Push (1, 2, 3 );

Alert (objb2.a );

// All A members in all B instances have changed !! This is not what we want to see in this example.

</Script> __

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/liaoxiaoli/archive/2011/01/11/6129682.aspx

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.