jquery Source Code Analysis: JQuery Tool method Callbacks detailed

Source: Internet
Author: User

Let's start with how callbacks is used: the first example

function A () {}

Function B () {}

var cb = $. Callbacks ();

Cb.add (a);

Cb.add (b);

Cb.fire (); //Will execute the a method first and then execute the B method

The above means: The Add method is to add the method to the array list, each time you execute, add a method. The fire method is to execute the methods in the list array sequentially.

Usage Scenario: second example

function A (n) {}

(function () {

function B (n) {}

})

You cannot call the B method here, because the B method is a local variable. Therefore, you can use callbacks to solve this problem.

function A (n) {}

var cb = $. Callbacks ();

Cb.add (a);

(function () {

function B (n) {}

Cb.add (b);

})

Cb.fire ("Hello");

At this point, the B method can be called by Cb.fire (), even if it is a local variable. and the parameter "Hello" in Fire can also pass in a A/b method.

Callbacks can pass 4 values, jquery.callbacks (options), options have four values: Once,memory,unique,stoponfalse.

In the first example, suppose we call two times cb.fire (); Then the first time a A, a, a, a, A/b method is called, the second time. But if you define CB this way, var cb = $. Callbacks ("once"); then only the first execution of the A/B method will not be executed the second time. Once means that only the methods in the list array are executed once, and then you call fire, and the methods in the list array are not executed.

The function of memory is:

var cb = $. Callbacks ();

Cb.add (a);

Cb.fire ();

Cb.add (b);

For the above code, method a executes, and the B method does not. But when you define CB, var cb = $. Callbacks ("Memory"); At this point, a, B method will execute. It has memory.

Unique role: Go to the weight, add if you add the same method, in the absence of a unique case, add several identical methods, you will execute the same method several times, but you pass in the unique, no matter how many times you add the same method, it will only be executed once.

The role of Stoponfalse:

function A () {return false;}

Function B () {}

var cb = $. Callbacks ();

Cb.add (a);

Cb.add (b);

Cb.fire ();

Method A, a, and B will execute. But if you define CB, var cb = $. Callbacks ("Stoponfalse"); only the A method is executed. Because the A method returns false, the function of Stoponfalse is to stop looping the list when the method returns false. Therefore, the B method will not execute.

Of course these four kinds of parameters, you can use combination, for example: var cb = $. Callbacks ("Once Memory");

Next, source parsing: Because the code is more, so give everyone a clue, $. Callbacks, return self; Self.add (a), List.push (a), Self.add (b), List.push (b), Self.fire ()->self.firewith, Private method F IRE (), loop list array, execute inside the A/b method. Please look at the code in this order, and then according to the 4 parameters respectively what meaning, and then look at the order. There is a detailed explanation of the code.

var optionscache = {};

function createoptions (options) {
var Object = optionscache[Options] = {};    //optionscache[once] = {}
Jquery.each (Options.match (core_rnotwhite) | | [], function (_, flag) { 

  Core_rnotwhite =/\s+/g, take character, Options.match (core_rnotwhite) = ["Once"], this regular is to handle multiple values, such as "once Match" into ["Once", "memory "]
object[flag] = true; //_ is the index value 0,flag is the value "once"
});
return object; //optionscache[once] = {"Once": true}
}

Jquery.callbacks = function (options) { //options has four values: Once,memory,unique,stoponfalse

options = typeof options = = = "string"? (optionscache[options] | | createoptions (OPTIONS)): Jquery.extend ({}, Options);

  When the parameter is passed in, it is a string, such as: once, then you will go to Optionscache to take the once property, if not previously, call the CreateOptions (once) method

var memory,
fired,
Firing,
Firingstart,
Firinglength,
Firingindex,
list = [],
stack =!options.once && [], //If there is once, then stack is false, if not, then stack will die [],if condition inside empty array is true, so in Fir E ()->firewith (), you can execute the methods in the list array again.
Fire = function (data) { //This is the place to actually execute the method in the list array
memory = options.memory && data;
fired = true;
firingindex = Firingstart | | 0;
firingstart = 0;
firinglength = list.length;
firing = true; //Is triggering a method in the list array
for (; list && Firingindex < firinglength; firingindex++) {
if (list[firingindex].apply (data[0], data[1]) = = = False && Options.stoponfalse ) {

//If the callback method returns false and there is an incoming stoponfalse parameter, it stops the for loop and stops executing the method later in the list array                      
memory = false;
Break ;
}
}
firing = false; //Method execution End
if (list) { ///When a method in the list array finishes executing, it will determine if the stack has a value
if (stack) {
if (stack.length) {
Fire (Stack.shift ()); //If there is a value, fire execution will be triggered again
}
} else if (memory) { ///If Once,stack is false, it will go else
list = []; //If a memory is passed in, only the list array will be emptied. As an example: var cb = $. Callbacks ("Once Memory"), Cb.add (a), Cb.fire (); Cb.add (b); Cb.fire (). Because there is once, it is executed only once, so the second fire is useless. Because there is memory, a, B method will be executed once. If there is no memory, the following else statement will be executed, and only the A method will be executed, and the B method will not execute.

} else {
self.disable (); //Block all fire operations behind
}
}
},
Self = {
add:function () { ///This Add method is the push method in the list array (the method that is called when the Fire is used)
if (list) { //[] is true
var start = list.length;
(function Add (args) {
Jquery.each (args, function (_, arg) {
var type = Jquery.type (arg);
if (type = = = "function") { //If the method is push to list
If (!options.unique | |!self.has (ARG)) { //If there is a unique judgment, such as passing in a unique, you must determine if there is this method in the list array, and if not, push to L The IST. The Self.has (Arg) method is to determine if there is an Arg method in the list array.
List.push (ARG);
}
} else if (arg && arg.length && type!== "string") {
Add (ARG); //The Add ([A, b]) is now executing the method add instead of Self.add.
}
});
}) (arguments); //Handle Add (A, B), add ([A, b]), while adding multiple methods
if (firing) {
firinglength = list.length;
} else if (memory) { ////The memory is undefined the first time the add is called. When the fire is called, if you pass in memory, the memory becomes true, and when you call add, you enter the IF statement to fire. So after you pass in the Memory,fire, call Add (b) and the B method executes.
Firingstart = start;
Fire (memory);
}
}
return this;
},
remove:function () { //Remove the corresponding method in the list array
if (list) {
Jquery.each (arguments, function (_, arg) {
var index;
While (index = Jquery.inarray (ARG, list, index)) >-1) {
List.splice (index, 1); //The Splice method of the array is mainly used to remove
if (firing) {
if (index <= firinglength) {
firinglength--;
}
if (index <= firingindex) {
firingindex--;
}
}
}
});
}
return this;
},
has:function (FN) { //jquery.inarray (FN, list), if FN returns 1 in list, no, returns-1
return fn? Jquery.inarray (FN, list) >-1:!!   (list && list.length); //If you do not pass in the value, determine if there is a value in the list, and the value returns TRUE.
},
empty:function () {
list = [];
firinglength = 0;
return this;
},
disable:function () { //After all operations are invalidated
list = stack = memory = undefined;
return this;
},
disabled:function () {
return!list;
},
lock:function () { ///will only lock the rear fire operation to invalidate the Cb.fire method.
stack = undefined;
if (!memory) {
self.disable ();
}
return this;
},
locked:function () {
return!stack;
},
firewith:function (context, args) { //the method in the list array is executed here
if (list && (!fired | | | stack)) { //fired is undefined on first call, fired is true on the second call, it depends on the stack.
args = args | |       []; //If a value is passed in the fire, it is args, if not passed, is an empty array
args = [Context, Args.slice args.slice (): args];
if (firing) { ////When the For loop executes a method in the list array, firing is true, when fire ()->firewith is called, the args are only added to the stack. When the method in the list array finishes executing. will be processed based on whether there is a value in the stack. As an example: var cb = $. Callbacks (), function A () {Cb.fire ()};funciton B () {};cb.add (a), Cb.fire (), executes a method, fires fire (), but does not execute the a method again, Because firing is true at this point, it will only add 1 to the stack, but wait until the execution of the B method is completed before the A method is re-executed. The private fire method will determine the value of the stack and, if there is a value, will continue to loop through the methods in the list array to execute the call.
Stack.push (args);

} else {
Fire (args); //The method that really executes the list array is a private method fire.
}
}
return this;
},
fire:function () { //fire method is actually the method of executing list
Self.firewith (this, arguments); //It is called the Firewith method. Arguments is the parameter passed in the fire, which can pass values to the methods in the list array.
return this;
},
fired:function () {
return!!   Fired; //Once the fire has been called, it will return true
}
};

return self; //returns the Self object. When calling var cb = $. Callbacks (), CB =self. So calling Cb.add,fire is actually the Self.add and fire method
};

Come on!

jquery Source Code Analysis: JQuery Tool method Callbacks detailed

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.