Objects and prototype in JavaScript (3)
In JavaScript objects and prototype (2), we mentioned that in the objects created using constructors, each object is independent, which will reduce the utilization of system resources, to solve this problem, we need to use the prototype objects mentioned below.
A prototype object
A prototype object is actually an Instance Object of the constructor. It is essentially different from a common instance object. It can contain shared attributes or methods of all instances of a specific type. In this way, if we need to modify the attributes or methods of all instances, we only need to modify one of them to influence all instances. Because the attributes and methods in the prototype are shared. We can see two diagrams:
Constructor Method
Prototype Mode
From the figure above, we can easily see whyCode"User1.show = user2.show;" returns true, because the show method shares all the objects created by the user constructor, rather than creating a show method for each object.
Each JavaScript function has the prototype attribute, which references an object, which is a prototype object. The initialization of the prototype object is empty. We can customize any attributes and methods in it. These methods and attributes will be inherited by the object created by the constructor.
The following code adds attributes and methods to a prototype:
Function User (name, age ){ // Constructor This . Name = Name; // Object Attribute This . Age = Age;} user. Prototype. ADDR = 'Hubei Wuhan '; // Add attributes to the prototype User. Prototype. Show =Function (){ // Add a method to the prototype Alert ( This . Name + '|' + This . Age );}; VaR User1 = New User ('zxc ', 22 ); // Create an instance VaR User2 = New User ('cxz', 21 ); User1.show (); // Call the show () method User2.show (); alert (user1.show = User2.show ); // If true is returned, the show method is shared. Alert (user1.addr ); // 'Hubei Wuhan' Alert (user2.addr ); // 'Hubei Wuhan'
However, there is a problem: If we have added an attribute in the constructor, the property in the prototype, and the attribute in the instance, what is the access attribute? Let's take a look at the following code:
Function User (name, age ){ // Constructor This . Name = Name; // Object Attributes This . Age = Age; This . ADDR = 'hubei Enshi' ;} User. Prototype. ADDR = 'Hubei Wuhan '; // Add attributes to the prototype VaR User1 = New User ('zxc ', 22 ); // Create an instance VaR User2 =New User ('cxz', 21 ); Alert (user1.addr ); // 'Hubei Enshi' Delete User1.addr; // Delete Object Attributes Alert (user1.addr ); // 'Hubei Wuhan' Delete User. Prototype. ADDR; alert (user1.addr ); // 'Undefined' User2.addr = 'wuhan' ; Alert (user2.addr ); // 'Wuhan'
From the code above, if we have declared the object attributes, prototype attributes, and instance attributes at the same time, the priority displayed during the call should be: instance attributes> Object Attributes> prototype attributes. This adopts the proximity principle: when calling the function, the system first checks whether the property is defined in the instance directly, and then returns the instance property. If the property is not in the instance, it searches for the property in the constructor. If the property is not in the instance, the system returns the property; if neither of the preceding methods is found in the prototype object, undefined is returned.
2. Dynamic Prototype
Some people may think that the writing in the code above is quite awkward, because the methods and attributes in the prototype are not the same as the object attributes and methods defined in the constructor. It is more intuitive to encapsulate them together, to solve this problem, we need to use the dynamic prototype mode;
// Dynamic Prototype Function User (name, age ){ // Constructor This . Name = Name; // Attribute This . Age = Age; This . ADDR = 'hubei Enshi' ; User. Prototype. ADDR = 'Hubei Wuhan '; // Add attributes to the prototype User. Prototype. Show = Function (){ // Add a method to the prototype Alert ( This . Name + '|' + This . Age + '|' + This . ADDR );};} VaR User1 = New User ('zxc ', 22 ); // Create an instance VaR User2 = New User ('cxz', 21 ); User1.show (); // Call the show () method User2.show (); alert (user1.show = User2.show ); // Returns true.
The above code looks more intuitive. However, there are still some minor problems, that is, when we create multiple instances, the method in the prototype will be re-created once if we do not create one instance. First test:
Alert ('start creating show ...... '); User. Prototype. Show=Function(){//Add a method to the prototypeAlert (This. Name + '|' +This. Age + '|' +This. ADDR) ;}; alert ('End creating show ...... ');
If we add the alert () above, the dialog box is displayed twice when no instance is created during running. This proves the previously mentioned re-creation problem. Although there is no additional increase in space, the time is increased because the re-creation is required every time.
To solve this problem, we should first determine whether the show method exists. If it does not exist, it will be created. if it already exists, it will not be re-created. The improved code is as follows:
If(This. Show = undefined ){//If the run method has not been createdAlert ('start creating show ...... '); User. Prototype. Show=Function(){//Add a method to the prototypeAlert (This. Name + '|' +This. Age + '|' +This. ADDR) ;}; alert ('End creating show ...... ');}
It is found that no matter how many instances are created, only two dialog boxes are displayed, which avoids unnecessary overhead.
3. Create a prototype using a literal
In addition to the prototype creation method mentioned above, we can also create a prototype using the literal method. The Code is as follows:
// Create a prototype literally Function User (name, age ){ // Constructor This . Name = Name; // Attribute This . Age = Age;} user. Prototype = {ADDR: 'Hubei Wuhan' , Show: Function () {Alert ( This . Name + '|' +This . Age + '|' + This . ADDR );}}; VaR User1 = New User ('zxc ', 22 ); // Create an instance VaR User2 = New User ('cxz', 21 ); User1.show (); // Call the show () method User2.show ();
It should be noted that:You cannot useLiteralThe prototype is rewritten. Once the prototype is rewritten, all attributes and methods defined in the original prototype will be cleared.. As follows:
// Create a prototype literally Function User (name, age ){ // Constructor This . Name = Name; // Attribute This . Age = Age;} user. Prototype = {ADDR: 'Hubei Wuhan' , Show: Function () {Alert ( This . Name + '|' + This . Age + '|' + This . ADDR );}}; // The prototype is rewritten. User. Prototype = {Other: 'No description ...... ' , Show: Function () {Alert ( This . ADDR );}}; VaR User1 = New User ('zxc ', 22 ); // Create an instance VaR User2 = New User ('cxz', 21 ); User1.show (); // Return undefined User2.show ();
It can be seen that once the prototype is rewritten, the variables and methods defined in the prototype are not saved. However, what we mean is that the prototype cannot be rewritten literally. Can we add new methods or attributes? The answer is yes, for example:
User. Prototype. addr1 = 'wuhan ';
In this way, the methods and attributes defined in the original prototype will not be cleared.
Iv. Summary
This article mainly introduces some basic knowledge about prototype. prototype can be used to share methods and attributes, or to extend object methods. For example, we can use the prototype method to extend the built-in object string method so that it has the left ()/right () function of VB, which is used to intercept the Left or Right side of the string.
There are some other knowledge in the prototype, which is not involved here. I will discuss it later ~~
by: On the triangle Lake