Prototype source code analysis-function. Prototype (2)

Source: Internet
Author: User

Next part: Prototype source code analysis -- function. Prototype part (1)

A Rough Review of the previous

In one example, there are two roads:

function handler(greet){
console.log(greet,this.name);
}
var obj = {
name : 'xesam'
}

1. Use call or apply to change the handler's scope, handler. Call (OBJ, 'Hello'). In this case, another function is required to wrap it.

2. Change handler to a method of OBJ so that it can call obj. Handler ()

 

The first part is the first road, and now it is the second road.

Since handler is to be converted into an OBJ method, it is impossible to directly grab it. obj. handler's handler is just a method of the same name as I defined (to be defined as other methods, such as XX). It is essentially different from the function handler defined in the example.

For the time being, we call this operation "methodization" (unofficial) and take a name such as the real method name in prototype ).

Refer to the description of bind. The specific implementation should be as follows:

Function. Prototype. methodize = function (){
VaR _ this = handler; // represents handler in the example
Return function (){
VaR caller = OBJ; // represents OBJ In the example
// Actual parameters of arguments
VaR ARGs = [Caller]. Concat (array. Prototype. Slice. Call (arguments ));
_ This. Apply (OBJ, argS );
}
}

After being changed to a common form, the call is:

Function handler (){
Console. Log (this. Name );
}
VaR OBJ = {
Name: 'xesam'
}

Function. Prototype. methodize = function (){
VaR _ this = This; // represents handler in the example
Return function (){
VaR caller = This; // represents OBJ In the example
// Actual parameters of arguments
VaR ARGs = [this]. Concat (array. Prototype. Slice. Call (arguments ));
_ This. Apply (this, argS );
}
}
OBJ. Handler = handler. methodize ();
OBJ. Handler ();

However, the implementation methods in prototype are slightly different:

Function methodize (){
If (this. _ methodized) return this. _ methodized;
VaR _ method = this;
Return this. _ methodized = function (){
VaR A = Update ([this], arguments );
Return _ method. Apply (null, a); // The first parameter applied here is not this, But null.
};
}

Therefore, the more obvious calling method in the original version is:

Function handler_1 (OBJ) {// returns the same effect as hangdler_1 (obj_1). However, obj_1.handler _ () is more object-oriented and is also used on Object-Oriented objects.
Console. Log (obj. Name );
}
VaR obj_1 = {
Name: 'xesam'
}
Obj_1.handler = handler_1.methodize ();
Obj_1.handler ();

In fact, if you understand bind, you can understand this operation. The extension of the entire function is implemented by using anonymous functions and scope transformations. It is flexible and not easy to understand at the same time.

Complicate a simple task. The main intention of doing so is simply to look at the function part, which will be mentioned later.

 

Another easy-to-lose method, wrap, is known as a reflection of the Nature of Aspect-Oriented Programming. In general, the method itself is packaged as the first parameter of the new method. It is mainly used to call the Method Before and After packaging, followed by the class part, you can call the methods of the parent class or subclass.

The specific code is similar to bind, So I directly gave it:

    Function.prototype.wrap =function(wrapper){
var _this = this;
return function(){
var params = [_this.bind(this)].concat(Array.prototype.slice.call(arguments, 0));
return wrapper.apply(this, params);
}
}

We still use instances to talk:

Function. Prototype. Bind = function (context ){
VaR _ method = This, argS = array. Prototype. Slice. Call (arguments, 1 );
Return function (){
VaR B = args. Concat (array. Prototype. Slice. Call (arguments, 0 ));
Return _ method. Apply (context, B );
}
}
Function. Prototype. Wrap = function (wrapper ){
VaR _ this = this;
Return function (){
VaR Params = [_ this. BIND (this)]. Concat (array. Prototype. Slice. Call (arguments, 0 ));
Wrapper. Apply (this, Params );
}
}
Function handler (){
Console. Log ('custom handler', this. Name );
}
VaR OBJ = {
Name: 'xishanzi'
}
OBJ. Handler = handler. Wrap (function (handlerbinded, content) {// the method mentioned above can be used here, But it avoids the trouble. I use a brain object to process it directly.
If (content ){
Console. Log (this. Name); // point to this
Console. Log (content );
} Else {
Console. Log (this. Name); // point to this
Handlerbinded (); // point to this
}
});
OBJ. Handler ();
OBJ. Handler ('test ');

Let's talk about it in the class.

 

Other methods include delay and defer.

There are two latency methods:

1. Loop XXXXX times and then execute it, just like the effect of sleep () or an endless loop, just like the effect of die ().

Second, setTimeout and setinterval.

The first method is mainly used to simulate sleep () for a test or something.

The second method is setTimeout if execution is delayed.

Another example:

Function handler (){
Console. Log ('execute ');
}

To delay handler 1 s execution, do not think about it:

setTimeout(function(){
handler();
},1000)

If you want to get the form of a method, you can just drop the parameter or something like BIND:

Function.prototype.delay = function(timeout){
var _this = this;
var _params = Array.prototype.slice.call(arguments,1);
var timer = setTimeout(function(){
_this.call(_this,_params);
},timeout);
return timer;
}
handler.delay(1000);

As for defer, it is just a small package for delay.

In delay, timeout is optional. Defer assigns a value of 0.01 to timeout directly (in my implementation, the unit of timeout is MS and that of prototype is S );

So

Handler. Defer () --> handler. Delay (10); // pay attention to the Unit. Here I implement the unit.

The only difference between the two delayed functions is the 10 in defer (10), which is delayed for 10 ms and then executed (the actual effect is that the JS interpreter runs immediately when it is idle, to prevent blocking of the current Code ).

This form is often seen:

    setTimeout(function(){

},0)

For more information about the JS timer mechanism, see the following articles:

[Reprinted] About setTimeout, understanding the Javascript Timing Mechanism

The third parameter of setTimeout and the small Application

 

The last method is to obtain the method parameter argumentnames.

    function handler(x,y){

}
handler.argumentNames();//['x','y']

 

This function only needs to understand handler. tostring (). handler. tostring () will return the string form of handler (including comments ).

Function handler (x, // X_1
Y/* Y_1 */){
}
Console. Log (handler. tostring ());
Print result:
'Function handler (x, // X_1
Y/* Y_1 */){
}'

Therefore, we only need to replace the comments and blank spaces with regular expressions.

Function. Prototype. argumentnames = function (){
VaR TMP = This. tostring (). match (/^ [\ s \ ()] * function [^ (] * \ ([^)] *) \)/) [1]; // obtain the parameter Section
VaR tmp_1 = TMP. Replace (/\/\/.*? [\ R \ n] | \/\*(? :. | [\ R \ n]) *? \ * \ // G, ''); // remove comments
VaR tmp_2 = tmp_1.replace (/\ s +/g, ''); // clear the blank
Return tmp_2.split (',')
}

There is a bit of judgment in prototype, just look at it:

Function. Prototype. argumentnames = function (){
VaR names = This. tostring (). match (/^ [\ s \ (] * function [^ (] * \ ([^)] *) \)/) [1]
. Replace (/\/\/.*? [\ R \ n] | \/\*(? :. | [\ R \ n]) *? \ * \ // G ,'')
. Replace (/\ s +/g, ''). Split (',');
Return names. Length = 1 &&! Names [0]? []: Names; // determines whether the parameter is null.
}

 

 

At this point, the update and merge functions are not mentioned, and all the methods are here.

If you have any errors, please point them out. Thank you.

For more information, see http://www.cnblogs.com/xesam /]
Address: http://www.cnblogs.com/xesam/archive/2011/12/18/2292739.html

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.