jQuery1.8.2源码解析之jQuery.Callbacks,已经在代码中添加了详细的注释,有需要的朋友看下边的代码就可以了。这样在使用时就方便了许多。
代码:
CopytoClipboardLiehuo.NetCodes引用的内容:[www.3672js.com]//StringtoObjectoptionsformatcache
//是对option的一个缓存,避免每次都要createOptions
//每一个option类似这样
//{
//memory:true
//,once:true
//,...
//}
varoptionsCache={};
//ConvertString-formattedoptionsintoObject-formattedonesandstoreincache
functioncreateOptions(options){
varobject=optionsCache[options]={};
jQuery.each(options.split(core_rspace),function(_,flag){
object[flag]=true;
});
returnobject;
}
/*
*Createacallbacklistusingthefollowingparameters:
*
*options:anoptionallistofspace-separatedoptionsthatwillchangehow
*thecallbacklistbehavesoramoretraditionaloptionobject
*
*Bydefaultacallbacklistwillactlikeaneventcallbacklistandcanbe
*"fired"multipletimes.
*
*Possibleoptions:
*
*once:willensurethecallbacklistcanonlybefiredonce(likeaDeferred)
*
*memory:willkeeptrackofpreviousvaluesandwillcallanycallbackadded
*afterthelisthasbeenfiredrightawaywiththelatest"memorized"
*values(likeaDeferred)
*
*unique:willensureacallbackcanonlybeaddedonce(noduplicateinthelist)
*
*stopOnFalse:interruptcallingswhenacallbackreturnsfalse
*
*/
jQuery.Callbacks=function(options){
//ConvertoptionsfromString-formattedtoObject-formattedifneeded
//(wecheckincachefirst)
//options也可以是一个对象
options=typeofoptions==="string"?
(optionsCache[options]||createOptions(options)):
jQuery.extend({},options);
var//Lastfirevalue(fornon-forgettablelists)
memory,
//Flagtoknowiflistwasalreadyfired
fired,
//Flagtoknowiflistiscurrentlyfiring
firing,
//Firstcallbacktofire(usedinternallybyaddandfireWith)
firingStart,
//Endoftheloopwhenfiring
firingLength,
//Indexofcurrentlyfiringcallback(modifiedbyremoveifneeded)
firingIndex,
//Actualcallbacklist
list=[],
//Stackoffirecallsforrepeatablelists
//只有在没有设置了once时,stack才存在
//stack用来存储参数信息(此时函数列表已经处于firing状态,必须将其他地方调用fire时的参数存储,之后再至此执行fire
stack=!options.once&&[],
//Firecallbacks
fire=function(data){
//如果设置memory,那么每一次fire的数据将会被保存在memory中,作为下次调用add时参数
memory=options.memory&&data;
fired=true;
firingIndex=firingStart||0;
//重置fireStarting为0,因为add操作(memory)可能改变它
firingStart=0;
firingLength=list.length;
firing=true;
for(;list&&firingIndex<firingLength;firingIndex++){
//如果设置了stopOnFalse参数,那么当函数列表中有某个函数返回false时,停止后面函数的执行,并且取消memory(如果设置了)
if(list[firingIndex].apply(data[0],data[1])===false&&options.stopOnFalse){
memory=false;//Topreventfurthercallsusingadd
break;
}
}
firing=false;
if(list){
//如果stack存在,那么将之前存储的第一个参数取出,继续fire,直到stack为空
if(stack){
if(stack.length){
fire(stack.shift());
}
//如果stack不存在(即设置了once)
//那么如果设置了memory,那么将之前函数列表清空,也就是说memory还在,add操作可以处罚函数立即执行
}elseif(memory){
list=[];
}else{
self.disable();
}
}
},
//ActualCallbacksobject
//实际返回的Callbacks对象
self={
//Addacallbackoracollectionofcallbackstothelist
//添加函数或者函数集(数组或者伪数组)到函数列表中去
add:function(){
if(list){
//First,wesavethecurrentlength
varstart=list.length;
(functionadd(args){
jQuery.each(args,function(_,arg){
vartype=jQuery.type(arg);
//如果arg是函数
//如果设置unique,则在list中查找是否函数已存在,若存在忽略掉,否则push进list
//如果没有设置unique,则直接push进list
if(type==="function"&&(!options.unique||!self.has(arg))){
list.push(arg);
//如果arg是数组或者伪数组,则递推push进list
}elseif(arg&&arg.length&&type!=="string"){
//Inspectrecursively
//递归(成员为函数集)
add(arg);
}
});
})(arguments);
//Doweneedtoaddthecallbackstothe
//currentfiringbatch?
//在添加函数(集)时
//如果函数列表正在依次执行回调函数(即firing状态),在某一个callback中执行add(fn)操作
//那么立即修改fireLength以便fire时函数列表能够执行到刚添加的函数(集)
if(firing){
firingLength=list.length;
//Withmemory,ifwe'renotfiringthen
//weshouldcallrightaway
//如果不是firing状态,并且设置了memory(肯定是在fired状态时才会执行这一步,因为memory是在fire一次后才会被负值)
//此时memory已经是上次fire是传递的参数,那么将会直接执行刚添加的函数集,而无需fire
}elseif(memory){
firingStart=start;
fire(memory);
}
}
returnthis;
},
//Removeacallbackfromthelist
//从函数列表中删除函数(集)
remove:function(){
if(list){
jQuery.each(arguments,function(_,arg){
varindex;
//while循环的意义在于借助于强大的jQuery.inArray删除函数列表中相同的函数引用(没有设置unique的情况)
//jQuery.inArray将每次返回查找到的元素的index作为自己的第三个参数继续进行查找,直到函数列表的尽头
//splice删除数组元素,修改数组的结构
while((index=jQuery.inArray(arg,list,index))>-1){
list.splice(index,1);
//Handlefiringindexes
//在函数列表处于firing状态时,最主要的就是维护firingLength和firgingIndex这两个值
//保证fire时函数列表中的函数能够被正确执行(fire中的for循环需要这两个值)
if(firing){
if(index<=firingLength){
firingLength--;
}
if(index<=firingIndex){
firingIndex--;
}
}
}
});
}
returnthis;
},
//Controlifagivencallbackisinthelist
//判断函数列表只能够是否包含给定的fn
has:function(fn){
returnjQuery.inArray(fn,list)>-1;
},
//Removeallcallbacksfromthelist
//清空函数列表
empty:function(){
list=[];
returnthis;
},
//Havethelistdonothinganymore
//使函数列表作废(不能再做任何事情)
disable:function(){
list=stack=memory=undefined;
returnthis;
},
//Isitdisabled?
//判断是否函数列表是否disabled
disabled:function(){
return!list;
},
//Lockthelistinitscurrentstate
lock:function(){
stack=undefined;
if(!memory){
self.disable();
}
returnthis;
},
//Isitlocked?
locked:function(){
return!stack;
},
//Callallcallbackswiththegivencontextandarguments
//和fire相似,不相同的是fireWith可以给定上下文参数
//fire中就是调用fireWith中的context就是this(函数列表对象self)
fireWith:function(context,args){
args=args||[];
args=[context,args.slice?args.slice():args];
//首先至少fire一次
//如果执行过一次了(fired),那么若stack存在(即没有设置once),将上下文环境和参数存储,否则什么都不做
if(list&&(!fired||stack)){
if(firing){
stack.push(args);
}else{
fire(args);
}
}
returnthis;
},
//Callallthecallbackswiththegivenarguments
//依次执行函数列表中的函数
fire:function(){
self.fireWith(this,arguments);
returnthis;
},
//Toknowifthecallbackshavealreadybeencalledatleastonce
//判断是否函数列表fire过(哪怕只有一次)
fired:function(){
return!!fired;
}
};
returnself;
};
如果您觉得本文的内容对您的学习有所帮助:
关键字:
jQuery