Callbacks源码
var callbacks=$.Callbacks(options) 创建实例
options.once 是否只执行一次,默认为否
options.memory:是否记录上次执行的回调函数参数,记录后,再次执行回调时将该参数推入queue参数数组中,默认为否
options.unique:保证回调函数的单一性,默认为否
options.stopOnFalse:当回调返回值为否时,是否终止回调函数执行,默认为否
配置项可以用字符串输入,将自动转化为对象形式,如"once"将转化为{once:true}
callbacks.add(fn) 添加回调函数
callbacks.fire("foo") 将参数"foo"传给各回调函数,并触发回调函数执行
callbacks.fireWith(content,“foo”) 回调函数上下文设为content,参数为"foo",并触发回调函数执行
callbacks.has(fn) 回调函数数组list是否有函数fn
callbacks.empty() 清空回调函数数组list
callbacks.remove(fn) 清除回调函数数组list指定的回调函数fn
callbacks.disable() 使回调函数中add和fireWith、fire方法均不可用,清空回调函数列表list、参数列表queue
callbacks.disabled() 判断实例是否不可用
callbacks.lock() 使回调函数中add方法均不可用,fireWith、fire方法根据memory有无设置有效性,若无且执行状态为不在执行中,fireWith、fire方法不可用
callbacks.lock() 判断实例是否锁死
源码书写的长处:
利用循环语句实现回调函数的顺序执行
利用循环语句+数组方法起始查询位清空数组中的重复项
利用转换类型的方式卡死if条件判断,进而阻止函数执行,如list回调函数列表在disable方法执行时设为"",而非[],使其在add方法的条件返回否值,阻止add方法执行
通过闭包驻留缓存信息如list回调函数数组、queue参数数组、memory前次执行参数记录等
源码:
define([ "./core", "./var/rnotwhite"// 返回匹配空白的正则 ], function( jQuery,rnotwhite ){ // 当options为字符串时,使用match方法分割空格类字符,各数组项作为object的属性,赋值为true后返回 function createOptions(options){ var object={}; jQuery.each( options.match( rnotwhite )||[], function(_,flag){ object[flag]=true;// 空数组不执行该语句 } ); return object; } /* * Create a callback list using the following parameters: * * options: an optional list of space-separated options that will change how * the callback list behaves or a more traditional option object * * By default a callback list will act like an event callback list and can be * "fired" multiple times. * * Possible options: * * once:是否只执行一次,默认为否 * memory:是否记录上次执行的回调函数参数,记录后,再次执行回调时将该参数推入queue参数数组中,默认为否 * unique:保证回调函数的单一性,默认为否 * stopOnFalse:当回调返回值为否时,是否终止回调函数执行,默认为否 */ jQuery.Callbacks=function(options){ // 将字符串格式的options转化成对象形式 options=typeof options==="string" ? createOptions(options) : jQuery.extend({},options); var firing,// 回调函数正在执行中状态 memory,// 前次执行时回调函数使用的参数 fired,// 回调函数已执行状态 locked,// 锁定回调函数,回调函数数组清空 list=[],// 所有回调都添加到list数组列表中 queue=[],// 数组形式存储回调函数的参数,每个数组项又是数组形式,其中首项为this,即Callbacks对象 firingIndex=-1,// 用以指向list回调函数数组的序号,便于循环执行回调 // 内部函数,执行回调 fire=function(){ locked=options.once; fired=firing=true; for ( ; queue.length; firingIndex=-1 ){ memory=queue.shift(); while ( ++firingIndex<list.length ){// 利用循环语句使回调函数顺序执行 if ( list[firingIndex].apply(memory[0], memory[1])===false && options.stopOnFalse ){ firingIndex=list.length; memory=false; } } } // 在不记录前次执行回调函数参数的前提下,当memory中的参数已执行,则将memory置为否 if ( !options.memory ){ memory=false; } firing=false; // once设为真,只执行一次的前提下,清空回调函数数组 if ( locked ){ if ( memory ){ list=[]; }else{ list="";// memory为否,即options.memory为否,此时add方法失效 } } }, self={ // 添加回调函数 add:function(){ if ( list ){ if ( memory && !firing ){ firingIndex=list.length-1;// 重新设置firingIndex的意义??? queue.push(memory); } (function add(args){ jQuery.each(args,function(_,arg){ if ( jQuery.isFunction(arg) ){ if ( !options.unique || !self.has(arg) ){ list.push(arg); } }else if( arg && arg.length && jQuery.type(arg)!=="string" ){ // 递归添加回调函数 add(arg); } } ); })(arguments); if ( memory && !firing ){// options.memory设为真,且没有回调函数执行的前提下,执行回调函数 fire(); } } return this; }, // 从list列表清除某些回调函数 remove:function(){ jQuery.each(arguments, function(_,arg){ var index; // 利用循环语句查找list回调函数数组中与arg函数相同的项 while ( ( index=jQuery.inArray(arg,list,index) ) > -1 ){ list.splice(index,1); if ( index<=firingIndex ){// 影响当前执行的Callbacks实例中的回调函数,函数删除后序号减1 firingIndex--; } } } ); return this; }, // 传入参数时判断函数是否list回调函数数组中,否则判断list中是否有回调函数 has:function(fn){ return fn ? jQuery.inArray(fn,list)>-1 : list.length>0; }, // 清空回调函数 empty: function(){ if ( list ){ list=[]; } return this; }, // locked设为[],list设为"",使add、fireWith方法失效 disable: function(){ locked=queue=[]; list=memory=""; return this; }, // 返回当前实例的fire、add方法是否有效,locked判断fire方法可能有效 disabled: function(){ return !list; }, // fire方法执行后,执行lock方法,清空参数队列,且locked设为[],使fireWith方法无效(需要locked为否) // 当memory和firing均为否时,list置为"",使add方法无效(需要list为否) lock: function(){ locked=queue=[]; if ( !memory && !firing ) { list=memory=""; } return this; }, // 返回当前实例是否被锁定,参数数组queue或回调函数数组list被清空 locked: function(){ return !!locked; }, // 执行回调函数,queue数组首项为Callbacks构造函数,其余项为给回调函数的参数 fireWith: function(context, args){ if ( !locked ) { args=args||[]; args=[context, args.slice?args.slice():args]; queue.push(args); if ( !firing ){ fire(); } } return this; }, // 执行回调函数,arguments以数组形式传给各回调函数 fire: function(){ self.fireWith(this,arguments); return this; }, // 返回回调函数是否被调用 fired: function(){ return !!fired; } }; return self; }; return jQuery; });