jQuery的回调对象Callbacks分析

Callbacks在jQuery中的地位是Deferred的基础,当然,也对外公开其方法。

Callbacks对象是统一管理多个函数的利器。其核心是参数options中的几个状态码的任意组合,非常灵活。

先来看看options

once: 只触发一次回调

memory: 如果是触发后状态,add后立即触发

unique: 添加相同回到函数,只触发其中一个

stopOnFalse: 回调中遇到return false, 后面都不执行。

首先是:

list = []

我们的工作就是在维护这个list

add: function() {
                if ( list ) {
                    // First, we save the current length
                    var start = list.length;
                    (function add( args ) {
                        jQuery.each( args, function( _, arg ) {
                            var type = jQuery.type( arg );
                            if ( type === "function" ) {
                                if ( !options.unique || !self.has( arg ) ) {
                                    list.push( arg );
                                }
                            } else if ( arg && arg.length && type !== "string" ) {
                                // Inspect recursively
                                add( arg );
                            }
                        });
                    })( arguments );
                    // Do we need to add the callbacks to the
                    // current firing batch?
                    if ( firing ) {
                        firingLength = list.length;
                    // With memory, if we're not firing then
                    // we should call right away
                    } else if ( memory ) {
                        firingStart = start;
                        fire( memory );
                    }
                }
                return this;
            },

其核心就是那个push方法。代码为什么这么多? 支持数组方式参数,遇到参数中有memory情况,执行方法。

remove方法:

remove: function() {
                if ( list ) {
                    jQuery.each( arguments, function( _, arg ) {
                        var index;
                        while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
                            list.splice( index, 1 );
                            // Handle firing indexes
                            if ( firing ) {
                                if ( index <= firingLength ) {
                                    firingLength--;
                                }
                                if ( index <= firingIndex ) {
                                    firingIndex--;
                                }
                            }
                        }
                    });
                }
                return this;
            },

其核心也是那个splice方法。

针对这个firing,后面介绍。

fire方法:

fire = function( data ) {
            memory = options.memory && data;
            fired = true;
            firingIndex = firingStart || 0;
            firingStart = 0;
            firingLength = list.length;
            firing = true;
            for ( ; list && firingIndex < firingLength; firingIndex++ ) {
                if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
                    memory = false; // To prevent further calls using add
                    break;
                }
            }
            firing = false;
            if ( list ) {
                if ( stack ) {
                    if ( stack.length ) {
                        fire( stack.shift() );
                    }
                } else if ( memory ) {
                    list = [];
                } else {
                    self.disable();
                }
            }
        }

其核心是哪个循环,拿出来一个个执行。

在这里有个stack

stack = !options.once && []

这是一个数组,干嘛用的呢?这是针对有些函数是延时函数,这种情况fire可能会延时,要先把它放到stack函数中。

这样,以上的firing状态也就可以理解了。

这就是Callbacks整体,其核心原理还算是比较简单了。

原文地址:https://www.cnblogs.com/pfzeng/p/4478641.html