jquery中的Callbacks方法为工具对象,它是一个多用途的回调函数列表对象,提供了一种强大的方法来管理回调函数的队列。其实Callbacks的思想跟观察者模式的思想相似
function aaa(m){
alert(m);
}
function bbb(n){
alert(n);
}
var cb = $.Callbacks();//实例化Callbacks对象
cb.add(aaa);//添加该函数到回调队列
cb.add(bbb);
cb.fire(2);//执行回调队列中的函数 执行后弹出2,2
另外创建$.Callbacks()对象时,可以传入配置参数,传入的参数可以是’once’,’memory’,’stopOnFalse’,’unique’,各个配置参数的意义如下:
配置参数可以有组合的情况,组合的参数需要以空格分隔
var cb1 = $.Callbacks('memory')
function ccc(){
alert(3);
}
cb1.add(ccc);
function ddd(){
alert(4);
}
cb1.fire();//弹出3 4
cb1.add(ddd);
Callbacks对象的公共方法如下
add(): 向回调列表中添加一个回调函数或回调的集合
disable(): 禁用回调列表中的回调
empty(): 从列表中删除所有的回调
fire():用给定的参数调用所有的回调
fired(): 确定回调列表中的回调是否已被执行
fireWith(): 访问给定上下文和参数列表的所有回调
has(): 确定列表中是否提供一个回调
lock(): 锁定当前状态的回调列表
locked(): 确定回调列表是否已被锁定
remove():从回调列表中删除一个回调或回调集合。
var rnotwhite = (/\S+/g);//匹配任何可见字符
// 如果options='memory' 返回options={memory:true} optionsCache{options:{memory:true}}
var optionsCache = {};
// Convert String-formatted options into Object-formatted ones and store in cache
//将字符串格式的options转换为object格式的options 并保存在cache中
function createOptions( options ) {
var object = optionsCache[ options ] = {};
jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
object[ flag ] = true;
});
return object;
}
jQuery.Callbacks = function( options ) {
// Convert options from String-formatted to Object-formatted if needed
// 从options中分隔参数
// (we check in cache first)
// 兼容处理 options的值有两种类型 一种为string 另一种为undefined 当为undefined时 将undefined改为{},避免以后的兼容处理
options = typeof options === "string" ?
( optionsCache[ options ] || createOptions( options ) ) :
jQuery.extend( {}, options );
var // Flag to know if list is currently firing标记list是否正在执行
firing,
// Last fire value (for non-forgettable lists) 如果参数中设定了memory 则记录最后一次执行callback的值,如果没设置memory,将该值设定为true
memory,
// Flag to know if list was already fired 标记list是否已执行
fired,
// End of the loop when firing 执行循环的终点
firingLength,
// Index of currently firing callback (modified by remove if needed)当前正在执行的callback是第几个
firingIndex,
// First callback to fire (used internally by add and fireWith) 第一个执行的callback索引
firingStart,
// Actual callback list
list = [],
// Stack of fire calls for repeatable lists
stack = !options.once && [],//当fire没有'once'限制时 stack存储在回调函数中fire的回调列表 防止出现死循环
// Fire callbacks
// data为数组 第一个参数为执行上下文 第二个参数为执行时的参数
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;//触发结束
// 触发完list后触发stack中的回调
if ( list ) {
if ( stack ) {
if ( stack.length ) {
fire( stack.shift() );
}
//只执行一次时触发的操作
} else if ( memory ) {
list = [];//清空数组 以后执行的回调中什么都没有
} else {
self.disable();//禁止以后的所有fire操作
}
}
},
// Actual Callbacks object
self = {
// Add a callback or a collection of callbacks to the list
// 添加回调函数
add: function() {
if ( list ) {
// First, we save the current length
// 确认存储位置,从数组的末尾添加
var start = list.length;
//针对add方法中传入多个参数的情况
(function add( args ) {
jQuery.each( args, function( _, arg ) {
var type = jQuery.type( arg );
if ( type === "function" ) {
//确定参数是否具有唯一性限制
//如果有唯一性限制 判断函数是否已包含在list中
if ( !options.unique || !self.has( arg ) ) {
list.push( arg );
}
//add([aaa,bbb])情况
} else if ( arg && arg.length && type !== "string" ) {
// Inspect recursively
add( arg );
}
});
})( arguments );
// Do we need to add the callbacks to the
// 如果在执行回调的时候添加回调,则修正回调队列的长度
if ( firing ) {
firingLength = list.length;
// With memory, if we're not firing then
// we should call right away
// 如果参数设定中含有memory 并在回调队列中含有未执行的回调函数 则直接执行回调函数
} else if ( memory ) {
firingStart = start;
fire( memory );
}
}
return this;
},
// Remove a callback from the list
// 删除回调函数
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;
},
// Check if a given callback is in the list.
// If no argument is given, return whether or not list has callbacks attached.
//----------------------------------判断函数是否已存在-------------
has: function( fn ) {
return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
},
// Remove all callbacks from the list
// -------------------清空所有----------
empty: function() {
list = [];
firingLength = 0;
return this;
},
// Have the list do nothing anymore
//
disable: function() {
list = stack = memory = undefined;
return this;
},
// Is it disabled?
disabled: function() {
return !list;
},
// Lock the list in its current state
// 将堆禁止
// 与disable的区别
lock: function() {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
},
// Is it locked?
locked: function() {
return !stack;
},
// Call all callbacks with the given context and arguments
fireWith: function( context, args ) {
if ( list && ( !fired || stack ) ) {
args = args || [];
args = [ context, args.slice ? args.slice() : args ];
//当回调函数执行时执行其他回调时,将执行回调的上下文以及参数信息添加到stack中
if ( firing ) {
stack.push( args );
} else {
fire( args );
}
}
return this;
},
// Call all the callbacks with the given arguments
// 当添加的函数执行时需要传入参数时,将参数通过fire传入
fire: function() {
self.fireWith( this, arguments );
return this;
},
// To know if the callbacks have already been called at least once
fired: function() {
return !!fired;
}
};
return self;
};
总结:callback中心思想就是一个观察者模式。通过add方法将回调函数添加到一个数组中,通过fire方法执行回调函数。它有四个配置参数分别为unique、once、memory和stopOnFalse。unique 主要是回调函数是唯一的,once方法是值fire方法只能执行一次,通过执行一次后将数组变为undefined实现,memory通过添加后立即执行实现,stopOnFalse通过将memory设置为false并跳出执行程序实现