Javascript: Prototype attribute usage instructions
Prototype is a method introduced in IE 4 and later versions for a certain type of objects, and it is particularly convenient: it is a method for adding methods to class objects! This may sound a little messy. Don't worry. I will explain this special method through the example below:
First, we need to first understand the concept of a class. Javascript itself is an object-oriented language, and its elements depend on a specific class according to different attributes. Common classes include: array, Boolean, date, function, and number), object, string, and other related class methods, it is also frequently used by programmers (here we need to distinguish between class attention and attribute sending methods), such as the push method of the array, the get method of the date series, and the split method of the string,
But in the actual programming process, I wonder if I feel the shortcomings of the existing method? The prototype method came into being! The following describes how to use prototype in a simple way:
1. The simplest example is prototype:
(1) number. Add (Num): function, Number Addition
Implementation Method: Number. Prototype. Add = function (Num) {return (This + num );}
Test: Alert (3). Add (15)-> show 18
(2) Boolean. Rev (): returns the inverse of a Boolean variable.
Implementation Method: Boolean. Prototype. REV = function () {return (! This );}
Test: Alert (true). Rev ()-> show False
Is it easy? This section only tells readers that this method is used in this way.
2. Implementation and enhancement of existing methods:
(1) array. Push (new_element)
Purpose: Add a new element to the end of the array.
Implementation Method:
Array. Prototype. Push = function (new_element ){
This [This. Length] = new_element;
Return this. length;
}
Let's further enhance him so that he can add multiple elements at a time!
Implementation Method:
Array. Prototype. pushpro = function (){
VaR currentlength = This. length;
For (VAR I = 0; I <arguments. length; I ++ ){
This [currentlength + I] = arguments [I];
}
Return this. length;
}
Should it be difficult to understand? Similarly, you can consider how to delete any location and multiple elements by enhancing array. Pop (the specific code will not be detailed)
(2) string. Length
Purpose: this is actually an attribute of the string class. However, JavaScript regards full and half-width as a character, which may cause some problems in some practical applications, now we use prototype to make up for this deficiency.
Implementation Method:
String. Prototype. cnlength = function (){
VaR arr = This. Match (/[^/x00-/xFF]/ig );
Return this. Length + (ARR = NULL? 0: arr. Length );
}
Test: Alert ("easewe space spaces". cnlength ()-> show 16
Here we use some regular expression methods and full-byte character encoding principles. because they belong to the other two relatively large classes, this article does not describe them. Please refer to the relevant materials.
3. Implementation of new functions, in-depth prototype: in actual programming, it is certainly not only the enhancement of existing methods, but also more functional requirements, here are two examples of solving the actual problem using prototype:
(1) string. Left ()
Problem: Anyone who has used VB should know the left function and take n characters from the left of the string. However, the full and half-width characters are considered as one character, this makes it impossible to intercept long strings in a mix of Chinese and English la S.
Purpose: truncates n characters from the left side of the string and supports full-width and half-width characters.
Implementation Method:
String. Prototype. Left = function (Num, mode ){
If (! // D +/. Test (Num) Return (this );
VaR STR = This. substr (0, num );
If (! Mode) return STR;
VaR n = Str. tlength ()-Str. length;
Num = num-parseint (n/2 );
Return this. substr (0, num );
}
Test:
Alert ("easewe space spaces". Left (8)-> display easewe Space
Alert ("easewe space spaces". Left (8, true)-> show easewe empty
This method uses the string. tlength () method mentioned above, and some good new methods can be combined between custom methods!
(2) date. daydiff ()
Function: Calculate the interval (year, month, day, week) between two date variables)
Implementation Method:
Date. Prototype. daydiff = function (cdate, mode ){
Try {
Cdate. getyear ();
} Catch (e ){
Return (0 );
}
VaR base = 60*60*24*1000;
VaR result = math. Abs (this-cdate );
Switch (mode ){
Case "Y ":
Result/= base * 365;
Break;
Case "M ":
Result/= base * 365/12;
Break;
Case "W ":
Result/= base * 7;
Break;
Default:
Result/= base;
Break;
}
Return (math. Floor (result ));
}
Test: Alert (new date (). daydiff (new date (329, 1)-> show
Alert (new date (). daydiff (new date (, 1), "M")-> show 10
Of course, it can be further expanded to get the response hour, minute, or even second.
(3) number. Fact ()
Role: factorial of a certain number
Implementation Method:
Number. Prototype. Fact = function (){
VaR num = math. Floor (this );
If (Num <0) return Nan;
If (num = 0 | num = 1)
Return 1;
Else
Return (Num * (num-1). Fact ());
}
Test: Alert (4). Fact ()-> 24
This method mainly demonstrates that the recursive method is also feasible in the prototype method!
Javascript prototype inheritance
Keywords: javascript prototype extend
The basic code for prototype-based inheritance in JS is as follows:
function(SubClass, SuperClass){
function F(){}
//
F.prototype = SuperClass.prototype;
// Construct prototype chain as the key to inheritance
SubClass.prototype = new F(); // 1
// Reset the constructor attribute of the prototype object of the subclass to the subclass itself.
SubClass.prototype.constructor = SubClass;
// Set the superclass attribute value of the subclass to prototype of the parent class.
SubClass.superclass = SuperClass.prototype; // 2
// Enable the sub-class to access the constructor of the parent class through baseconstructor.
SubClass.baseconstructor = SuperClass;
}
The above code has two points worth attention:
(1) The new F () method is used at Statement 1. Why is it necessary to create a new F object? First, let's look at the results of the following code:
function SP(){this.cls = "super class";}
SP.prototype.print(alert(this.cls););
function SB(){}
SB.prototype = SP.prototype
SB.prototype.print(alert("changed by subclass"));
new SP().print(); // output: changed by subclass
The results show that the changes to the SB prototype object affect the SP, that is, the Sb and SP share the same prototype object. This does not conform to the meaning of inheritance. If
SB.prototype = SP.prototype
Changed:
SB.prototype = new SP()
This problem can be avoided. This is why code 1 uses new F () instead of F. prototype.
There is another question here: what is the specific role of F here? Why should I add F instead of using new superclass ()?
Let's take a look at the following code:
function SP(){this.cls = "super class";}
SP.prototype.print(alert(this.cls););
function SB(){}
SB.prototype = new SP();
new SB().print(); // super class
function F(){}
F.prototype = SP.prototype;
SB.prototype = new F();
new SB().print(); // undefined
In the code, the print function is executed twice to print the results of "super class" and "undefined. That is to say, when this function is executed for the second time, the SB object does not have the CLS attribute, which is the role of adding an empty F function. It can avoid obtaining the attributes defined in the parent class SP function (this. XXX) in the subclass sb ).
(2) subclass. superclass at Statement 2 is superclass. prototype, rather than superclass itself. Reference
Http://bbs.51js.com/viewthread.php? Tid = 72688 & page = 1 & extra = # views of a user on pid556697:
Prototype inheritance subclass inherits superclass through prototype skillful processing. This is a progressive recursive process. Therefore, it is reasonable to specify the prototype specified by superclass to superclass, subclass is also needed for future calls. superclass. method. if the call is specified as you do, subclass is required. superclass. prototype. method. call is more complicated.
Subclass. superclass. Call (this) method is not as intuitive as subclass. superclass. constructor. Call (this) Method
In addition, constructor is a constructor. It also shows that the call is better, the style is consistent, and it is easier to understand with fewer hidden rules. There is no need to learn the Java method, in addition, if the superclass does not have a constructor, The superclass will be called step by step to the parent class at the upper level until the top.
EXT inheritance is also implemented based on prototype chain.
Http://www.javaeye.com/topic/195409 has a detailed analysis of its inheritance method implementation. However, one of the codes has not been fully understood:
if(spp.constructor == Object.prototype.constructor){
spp.constructor=sp;
}
In this Code, there are two possibilities when the if condition is true: (1) SP itself is an object; (2) When a function object is created, the constructor attribute value of its prototype object always points to the function object itself. Therefore, another possibility is that the SP display changes its prototype object, and the constructor attribute value of the new object points to the object. There is no meaning in processing the 1st cases, because spp. constructor must be equal to SP; then it is only possible in the second case. The puzzling question is "why is it necessary to reset the constructor value of the protoype object of the parent class only when the child class is inherited, rather than setting it when the prototype object is displayed and changed ". Why?
Here we need to reset the constructor value? Based on the preceding and following code:
spp = sp.prototype;
sb.superclass=spp;
if(spp.constructor == Object.prototype.constructor){
spp.constructor=sp;
}
Similar to setting a subclass superclass in statement 2, The superclass attribute of Sb is set to spp, which is the prototype object of its parent class sp. To access the parent class itself, you can only use the constructor attribute of spp. Therefore, you need to determine the constructor attribute and reset it to the parent class sp. That is, the reason for adding this statement is to ensure that the constructor of the parent class is called correctly in the subclass, rather than the object.
Example: <SCRIPT type = "text/JavaScript">
// Prototype inheritance
Function classa (){
This. methoda = function (){
Alert ('classa. methoda ()');
}
}
Function classb (){
This. methodb = function (){
Alert ('classb. methodb ()');
}
}
Classb. Prototype = new classa ();
VaR A = new classb ();
A. methoda ();
A. methodb ();
</SCRIPT>