GitHub = GitHub = GitHub = GitHub

This code is

My – jQuery 1.0.2. Js

My – jQuery 1.0.3. Js

It is recommended to download the source code and then learn according to the article ideas, it is best to think while knocking a few times.

Basic concepts of Callbacks

1.$. Callbacks are used to manage function queues. 2. Add handler functions to the queue with add() and execute them with fire. Callbacks are used internally in jQuery to provide basic function functions for.Ajax,$.deffed, etc. It can also be in some components of similar functions, such as self-developed plug-ins

Second, the Callbacks API

  • 1.$.callbacks, get the instance
  • 2.add()Add functions to the internal queue
  • 3.fire()Find and execute the functions in the queue in turn
var cb = $.callbacks();
cb.add(function(){
console.log('add one');
});
cb.add(function(){
console.log('add two');
});
cb.add(function(){
console.log('add three'); }); Cb.fire () // Add one add two add threeCopy the code

Specific functions of the Callbacks parameter

Callbacks support four specific functions in the form of string arguments

  • 1.once
    • The function queue is executed only once
Var cbOne = $.callbacks ('once');
cbOne.add(function(){
    console.log("this is cbOne1");
});
cbOne.add(function(){
    console.log("this is a cbOne2"); }); Cbone.fire (); cbone.fire (); cbOne.fire(); Result: This is cbOne1 This is a cbOne2Copy the code
  • 2.unique
    • Functions added to the internal queue remain unique and cannot be added repeatedly
 // unique
var cbUnique = $.Callbacks('unique');
function demo(){
    console.log("this is a cbUnique"); } cbUnique.add(demo,demo); cbUnique.fire(); // This is a cbUniqueCopy the code
  • 3.stopOnFalse
    • The functions in the inner queue are executed in sequence, and when one function returns false, the remaining functions are stopped.
Var cbDemo = $.callbacks (); cbDemo.add(function(){
    console.log("this is cbDemo 1");
    return false;
    
},function(){
    console.log("this is cbDemo 2"); }) cbDemo.fire(); This is cbDemo 1 this is cbDemo 2 var cbStopOnFalse = $.callbacks ('stopOnFalse');
cbStopOnFalse.add(function(){
    console.log("this is a cbStopOnFalse 1");
    return false;
},function(){
    console.log("this is a cbStopOnFalse 2"); }); cbStopOnFalse.fire(); Output: This is a cbStopOnFalse 1Copy the code
  • 4.memory
    • When the parameter queue fire passes once, the parameters of the current fire are recorded internally. The next time add is called, the recorded arguments are passed to the newly added function and the newly added function is executed immediately.
Var cbNoMemory = $.callbacks (); cbNoMemory.add(function(){
    console.log("this is a cbNoMemory 1"); }); cbNoMemory.fire(); Output: this is a cbNoMemory 1 cbNoMemory. Add (function (){
    console.log("this is a cbNoMemory 2"); }); Var cbMemory = $.callbacks ('memory');
cbMemory.add(function(){
    console.log("this is a cbMemory 1"); }); cbMemory.fire(); Output: This is a cbMemory 1 this is a cbMemory 2 cbmemory. add(function(){
    console.log("this is a cbMemory 2");
})
Copy the code

Learn about Callbacks from event functions

1. Events are usually used in conjunction with functions, so that the execution of the function can be driven by the occurrence of events.

Rule: One event for one event function In cases where one event corresponds to more than one function, the latter overrides the former.

Q: So can we have a way to change the one-to-one model of events?

Solution: Achieve a one-to-many event model by placing events in an array and executing them sequentially through a sequence of numbers.

// A one-to-many event modelfunction one(){
    console.log("one");
    
};
function two(){
    console.log("two");
    
};
function three(){
    console.log("three");
    
};
function four(){
    console.log("four"); }; var clickCallBack = [one,two,three,four]; // Define a button <button id= in the body"btn"</button> $("#btn").click(function(){
   var _this = this;
   clickCallBack.forEach(function(fn){ fn.call(_this); })}); // Output result: one three three fourCopy the code

2.Callbacks are not just an array. You can think of it as a container.

Five, start to analyze

We have already called the Callbacks API with jQuery and output the content. We have started to work backwards with two methods,add(),fire() and four parameters,”once”,”unique”,”menory”,”stopOnfalse”.

The first is the add() method, which converts the options passed through to a true array, then iterates through the array to select data of type “Function” and adds the data to an empty array for execution. Only code snippets, complete code download address: source download

Core code snippet:

add:function() {/ / Array. Prototype. Slice. The call (the arguments pseudo arrays turn true var args = Array. The prototype. Slice. The call (the arguments); start = list.length; Function args. ForEach (Function args.function(fn){// Retrieves whether fn is Functionif (toString.call(fn) === "[object Function]"List.push (fn) {// unique does not exist and fn is in list. }}});Copy the code

Fire () method: Fire simply executes the methods added to the queue as a regular output, requiring a middleware fireWith to provide context. Core code:

var fire = function(data){ index = 0; length = list.length; // loop through the listfor(; index < length; Index ++){// Find list[index] by traversingfalseIf options has stopOnfalse, traversal stopsif (list[index].apply(data[0],data[1]) == false) {break; }}}Copy the code
// define a context-binding function fileWith:function(context,arguments){
    var args = [context,arguments];
        fire(args);
}
Copy the code
fire:function(){
    self.fileWith(this,arguments);
},
Copy the code

At this point the above code can implement the add() and fire() methods. Secondly we are considering the case of four arguments. First we will consider the case of stopOnfalse.

The stopOnfalse parameter takes effect only when the queue function added by add() returns false after fire() is called, so the first thing we should think about is fire().

Check if optionSS has stopOnfalse when iterating through the method.

Core code:

 var fire = function(data){ // memory memory = options.memory && data; // Starts index = 0; length = list.length; // loop through the listfor(; index < length; Index ++){// Find list[index] by traversingfalseIf options has stopOnfalse, traversal stopsif (list[index].apply(data[0],data[1]) == false && options.stopOnfalse){
            break; }}Copy the code

The once argument works if the fire() method remains after the first execution of once.

The affected phase is fire(). Define an argument to record the first time fire() is executed. Then execute the fire() method to determine if the once argument is passed.

Core code:

var fire = function(data){
index = 0;
length = list.length;
startAdd = true; // It is used to record whether the fire() method is easy to execute"once"The // iterates through the list loopfor(; index < length; Index ++){// Find list[index] by traversingfalseIf options has stopOnfalse, traversal stopsif (list[index].apply(data[0],data[1]) == false && options.stopOnfalse){
        break; }}}Copy the code
// define a context-binding function fileWith:function(context,arguments){ var args = [context,arguments]; // non-fire does limit callsif(! options.once || ! startAdd) { fire(args); }},Copy the code

The memory parameter is valid only if the add() method remains valid after the fire() method is executed.

In the add() phase, memory is affected. In the fire() phase, memory is affected. In the add() phase, memory is affected, and in the fire() phase, index is affected.

Core code:

var fire = function(data){ // memory memory = options.memory && data; / / in order to prevent the memory once again call time defines memoryStarts index = memoryStarts | | 0; start = 0; length = list.length; startAdd =true; // It is used to record whether the fire() method is easy to execute"once"The // iterates through the list loopfor(; index < length; Index ++){// Find list[index] by traversingfalseIf options has stopOnfalse, traversal stopsif (list[index].apply(data[0],data[1]) == false && options.stopOnfalse){
            break; }}}Copy the code
// memory 
    if (memory) {
        memoryStarts = start;
        fire(memory);
    }
Copy the code

The most difficult parameter is unique.

The unique parameter takes effect if the same method is added () multiple times and the change is performed only once.

Ideas: The unique influence phase is the add() phase, so it’s best if we intercept it here, so we decide when we add() that if the unique parameter exists, then we don’t let the same method be pushed to the queue, not added to the queue, then we won’t execute the method again.

[].indexof. Call () : [].indexof. Call () : We can use ES6’s set to filter duplicate values and we do this using method one. Core code:

// Add method add:function() {/ / Array. Prototype. Slice. The call (the arguments pseudo arrays turn true var args = Array. The prototype. Slice. The call (the arguments); start = list.length; Function args. ForEach (Function args.function(fn){// Retrieves whether fn is Functionif (toString.call(fn) === "[object Function]") {// unique does not exist and fn is in the list so we can add fn to the listif(!options.unique || !self.has(fn,list)) {
                list.push(fn);
            }
        }
    });
Copy the code
has:function(fn,array){
    return arr = jQuery.inArray(fn,array) > -1;
}
Copy the code
jQuery.inArray = function (elem,arr){
    returnarr == null? -1:[].indexOf.call(arr,elem); }Copy the code

At this point, done!! Now that you’ve done the Callbacks() implementation, what have you learned?

other

JQuery source code analysis series directory address: GitHub

JQuery source code analysis series is expected to write about ten, aimed at deepening the understanding of native JavaScript part of the knowledge and in-depth, JQuery core functions, selectors, Callback principle, delayed object principle, event binding, jQuery architecture, delegate design mode, DOM operation, animation queue, etc. If there is any mistake or not precise place, please be sure to give correction, thank you very much. If you like it or are inspired by it, please welcome star⭐️ to encourage the author.

Concern about the public number reply: learn to receive the front end of the latest and most complete learning materials, but also into the group and big guy together to learn and exchange