Make a joke before writing an article to make the atmosphere more lively --
Principal: "Sir, I have good news. A bad news is about your son ." Parent: "Principal, let's talk about bad news first !"
Principal: "The bad news is that your son is very female ." Parent: "What about the good news ?" Principal: "The good news is that he is the school flower ."
Let's get down to the truth and put the original address first:
http://blog.vjeux.com/2011/javascript/how-prototypal-inheritance-really-works.html
This is the first time I have translated other people's articles. If not, please forgive me.
Full text:
Javascript-how is prototype inheritance implemented?
On the Internet, we can see everywhere that JavaScript is prototype-based inheritance. By default, JavaScript only provides a special prototype inheritance through the new operator.
Therefore, many comments and explanations are hard to understand. This article analyzes the essence of prototype inheritance and how to use prototype inheritance.
Prototype inheritance Definition
When we encounter prototype inheritance, we usually see the following explanation:
When you need to read the attributes of an object, JavaScript searches up the prototype chain until matching attributes are found.
In most JavaScript implementations, __proto _ indicates the next object of the prototype chain,
In the following content, we will find the difference between _ PROTO _ and prototype.
Note :__ PROTO _ is non-standard, so it should not appear in your official code. This attribute is used in this article only for clarity, not practicality.
The following code illustrates how the JavaScript engine retrieves an attribute.
Function getproperty (OBJ, Prop ){
If (obj. hasownproperty (PROP ))
Return OBJ [prop]
Else if (obj. _ PROTO __! = NULL)
Return getproperty (obj. _ PROTO __, prop)
Else
Return undefined
}
Let's take a common example: two coordinate points. A vertex has two coordinates, X and Y, and a print method.
Following the prototype inheritance definition above, we generate an object with three attributes (x, y, and print). To create a new vertex, use _ PROTO _ to create a vertex object.
VaR point = {
X: 0,
Y: 0,
Print: function () {console. Log (this. X, this. Y );}
};
VaR P = {X: 10, Y: 20, _ PROTO __: point };
P. Print (); // 10 20
Javascript weird prototype inheritance
What is confusing is that no one who cited the above definition to teach JavaScript prototype inheritance has provided code similar to the above,
Instead, it is similar to the following code:
Function Point (x, y ){
This. x = X;
This. Y = y;
}
Point. Prototype = {
Print: function () {console. Log (this. X, this. Y );}
};
VaR P = new point (10, 20 );
P. Print (); // 10 20
This is completely different from the code above. Point is now a function. We use the prototype attribute and the new operator, which is really hard.
How does the new operator work?
Brendan eich (the inventor of JavaScript) wants to make JavaScript look similar to some traditional object-oriented languages (such as Java and C ++), in which traditional languages, the new operator is used to create an instance of a class. Therefore, the new operator is also implemented.
C ++ has the constructor concept to initialize an instance attribute. Therefore, the new operator must be used in a function.
Object methods need to be stored locally. Since we are using the original type language, we put it in the prototype attribute of the function.
The new operator is like an F function and the parameter new F (arguments). The steps are as follows:
1. Create an instance of the class and get a _ PROTO _ pointing to F. Null Object of protoype.
2. initialize the empty object, that is, the instance. In this step, the F function is called and the parameter is passed in, pointing this to the instance in the first step.
3. Return this instance
It may not be easy to understand. We use code to implement his steps:
Function new (f ){
/* 1 */var n = {'_ PROTO _': f. Prototype };
Return function (){
/* 2 */f. Apply (n, arguments );
/* 3 */return N;
};
}
The following is a small example of how it works:
Function Point (x, y ){
This. x = X;
This. Y = y;
}
Point. Prototype = {
Print: function () {console. Log (this. X, this. Y );}
};
VaR p1 = new point (10, 20 );
P1.print (); // 10 20
Console. Log (P1 instanceof point); // true
VaR P2 = new (point) (10, 20 );
P2.print (); // 10 20
Console. Log (P2 instanceof point); // true
Real prototype inheritance in Java SDK
The javascript standard only provides the class new operator. Nevertheless, Douglas crockford finds a way to use new to implement real prototype inheritance. He wrote the following object. Create Function:
Object. Create = function (parent ){
Function f (){}
F. Prototype = parent;
Return new F ();
};
This looks weird, but it is very simple. This function only creates a new object, and its prototype can point to any position you want to point to. If we can use _ PROTO __at will, we can also write it like this:
Object. Create = function (parent ){
Return {'_ PROTO _': parent };
};
The following example uses prototype inheritance to rewrite the above coordinate point:
VaR point = {
X: 0,
Y: 0,
Print: function () {console. Log (this. X, this. Y );}
};
VaR P = object. Create (point );
P. x = 10;
P. Y = 20;
P. Print (); // 10 20
Conclusion:
We discussed what prototype inheritance is and how Javascript is implemented in a special way.
However, the real prototype inheritance (object. Create and _ PROTO _) has some disadvantages:
1. Not a standard method: __proto _ is not standard or even outdated. The implementation of native object. Create method and Douglas crockford is not completely equivalent.
2. Insufficient optimization: object. Create (native or imitated) is not as optimized as the new operator, and the speed gap may reach 10 times.