(function( jQuery ) {

 // String to Object flags format cache
var flagsCache = {}; // Convert String-formatted flags into Object-formatted ones and store in cache
// 将字符串形式的flags转换成对象形式,并且存到cache中,例: "once memory" => {"once":true,"memory":true}
function createFlags( flags ) {
var object = flagsCache[ flags ] = {},
i, length;
flags = flags.split( /\s+/ );
for ( i = , length = flags.length; i < length; i++ ) {
object[ flags[i] ] = true;
}
return object;
} /*
* 用以下参数创建一个回调函数列表:
*
* flags: 可选的以空格分隔的flags,会影响回调函数列表的行为
*
*
* 默认情况下,回调函数列表的行为如同一个事件回调函数列表一样,并且可以触发多次。
*
* 可选的 flags:
*
* once: 会确保回调列表只被触发一次(像Deferred一样), 这个不会阻止memory模式,也就是说 "once memory"的参数下 虽然只能fire一次,但是fire后再add 还是有效果的
*
* memory: 会记录上一次fire的上下文(一般是$.callbacks自身)和参数,并且会立即以最近一次fire记录下的上下文和参数执行新添加进来回调函数 (像Deferred一样)
* 具体看 (1) 88行 memory = !flags.memory || [ context, args ]; 保存memory模式下的 函数上下文和参数
* (2) 127-130行 self.add添加回调函数时候的处理
*
* unique: 会确同一个回调函数只在列表中出现一次
*
* stopOnFalse: 其中一个回调函数返回false即停止调用其余函数
*
*/
jQuery.Callbacks = function( flags ) { // Convert flags from String-formatted to Object-formatted
// (we check in cache first)
flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; var // 实际存放回调函数的容器
list = [], // 用以存放可重复fire(即非once模式),重复fire的回调函数 例: 在一个回调函数体里边也调用了fire的情景
// 另外这个stack 还用以标示整个回调列表是否处于锁定状态(仅仅判可不可触发fire, 还是可以add, remove的) 205行 + 192-202行
stack = [], // 上次fire的上下文和参数,
// 可能的值: (1) [context,args]
// (2) true , 非记忆执行上下文和参数 或者 stopOnFalse模式下有返回为false的回调函数
memory,
// 标识当前是否处于fire状态
firing,
// fire第一个执行的回调函数在list中的索引位置 (内部fireWith使用和add导致list个数变化时修正执行中的索引位置 128行)
firingStart,
// 循环的结尾位置 (如果在firing状态下self.add添加新函数和self.remove移除函数时候会调整 123行 146行 )
firingLength,
// 当前触发的函数索引 ,需要的时候会调整
firingIndex,
//工具方法: 添加一个或多个(args为数组时)函数到list
add = function( args ) {
var i,
length,
elem,
type,
actual;
for ( i = , length = args.length; i < length; i++ ) {
elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
// 递归检查
add( elem );
} else if ( type === "function" ) {
// 非unique模式且新回调函数不存在
if ( !flags.unique || !self.has( elem ) ) {
list.push( elem );
}
}
}
},
//工具方法: 触发回调函数
fire = function( context, args ) {
args = args || [];
memory = !flags.memory || [ context, args ];
firing = true;
firingIndex = firingStart || ;
firingStart = ;
firingLength = list.length;
for ( ; list && firingIndex < firingLength; firingIndex++ ) {
if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
memory = true; // 标记为终止 注意看106行, 销毁$.callbacks
break;
}
}
firing = false; // 标记执行结束
if ( list ) {
if ( !flags.once ) { // fire完后检查是否有回调函数内部重复fire保留下来的执行上下文和参数
if ( stack && stack.length ) {
memory = stack.shift();
self.fireWith( memory[ ], memory[ ] );
}
} else if ( memory === true ) { // stopOnFalse
self.disable();
} else {
list = [];
}
}
},
// 实际的回调函数对象
self = {
//实例方法: 添加一个或多个(args为数组时)函数到list
add: function() {
if ( list ) {
var length = list.length;
add( 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, unless previous
// firing was halted (stopOnFalse)
} else if ( memory && memory !== true ) {
firingStart = length;
fire( memory[ ], memory[ ] );
}
}
return this;
},
// 从列表中移除函数
remove: function() {
if ( list ) {
var args = arguments,
argIndex = ,
argLength = args.length;
for ( ; argIndex < argLength ; argIndex++ ) {
for ( var i = ; i < list.length; i++ ) {
if ( args[ argIndex ] === list[ i ] ) {
// 在firing时移除函数,需要修正当前索引firingIndex和长度firingLength
if ( firing ) {
if ( i <= firingLength ) {
firingLength--;
if ( i <= firingIndex ) {
firingIndex--;
}
}
}
// Remove the element
list.splice( i--, );
// 如果是unique模式(这时不会有重复的函数),移除一次就可以了
if ( flags.unique ) {
break;
}
}
}
}
}
return this;
},
// 判断指定回调函数是否存在
has: function( fn ) {
if ( list ) {
var i = ,
length = list.length;
for ( ; i < length; i++ ) {
if ( fn === list[ i ] ) {
return true;
}
}
}
return false;
},
// Remove all callbacks from the list
empty: function() {
list = [];
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
lock: function() {
stack = undefined;
if ( !memory || memory === true ) {
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 ( stack ) { // stack=[] 也是true
if ( firing ) {
if ( !flags.once ) {
stack.push( [ context, args ] );
}
} else if ( !( flags.once && memory ) ) {
fire( context, args );
}
}
return this;
},
// Call all the callbacks with the given arguments
fire: function() {
self.fireWith( this, arguments );
return this;
},
// To know if the callbacks have already been called at least once
fired: function() {
return !!memory; // 其实这个有问题, 当调用disable() 的时候 memory==undefined
}
}; return self;
}; })( jQuery );

下面是一些检验这些参数逻辑的代码:

      /*
jquery.Callbacks
*/
// var testUrl="http://www.runoob.com/try/ajax/demo_test.php";
// var callbacks=new jQuery.Callbacks("memory");
// callbacks.add(function(){alert("first callback")});
// callbacks.add(function(){alert("second callback")});
// callbacks.fire();
// memory
// callbacks.add(function(){alert("third callback")}); var callback2=
jQuery.Callbacks("once memory"), // once 表示回调函数列表只会fire一次,但是还会运行memory机制,也不限制回调函数列表里边有多个相同的函数(可以用unique 去重)
something = true;
function fn1(args)
{
alert('fn1 args:'+args);
console.log(this);
if(something){
callback2.fire(" test:第2次触发");
callback2.fire(" test:第3次触发"); //fire内部再触发的话 先放入stack中
something=false;
}
}
function fn2(){
alert('fn2');
}
callback2.add(fn1);
callback2.add(fn2); callback2.fire('测试:第1次触发');
callback2.fire('测试:第4次触发'); //once模式 只会fire一次, memory在add的时候促发
callback2.add(fn2);

源码地址

04-25 19:04
查看更多