// optionsCache : { 'once memory' : { once : true , memory : true } } var optionsCache = {}; // once memory,options.match( core_rnotwhite )=[once, memory],function( _, flag )={once:true,memory:true} function createOptions( options ) { var object = optionsCache[ options ] = {};//中括号就是json的点,没有点了。 jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { object[ flag ] = true; }); return object; } /* var cb = $.Callbacks(); function aaa(){ alert(1); } cb.add(aaa); (function(){ function bbb(){ alert(2); } cb.add(bbb); })(); cb.fire();//1 2 */ jQuery.Callbacks = function( options ) {//类的静态方法 //options 可选: once memory unique stopOnFalse //方法:add remove has empty disable disabled lock locked fireWith fire fired //什么都不写走jQuery.extend( {}, options ),返回空{},不这样写,如果options===undefined,后面还要做兼容。 options = typeof options === "string" ? ( optionsCache[ options ] || createOptions( options ) ) : jQuery.extend( {}, options );//options={once:true,memory:true} var memory, fired, firing, firingStart, firingLength, firingIndex, // 添加的所有方法 list = [], stack = !options.once && [], fire = function( data ) { memory = options.memory && data;//有memory返回true 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 ) {// 函数返回false,有stopOnFalse属性就不向下执行 memory = false; //memory也要置为false break; } } firing = false;//触发结束 if ( list ) { if ( stack ) { if ( stack.length ) { fire( stack.shift() ); } } else if ( memory ) { list = []; } else { self.disable(); } } }, self = {//对外部接口 add: function() { if ( list ) {//list一上来是空数组,会返回真, var start = list.length; (function add( args ) {//args是形参 jQuery.each( args, function( _, arg ) {//遍历传进来的多个方法名, var type = jQuery.type( arg ); if ( type === "function" ) { if ( !options.unique || !self.has( arg ) ) {//不是unioqye,或者是unipue但是没有 list.push( arg ); } } else if ( arg && arg.length && type !== "string" ) {//数组,嵌套 add( arg ); } }); })( arguments );//arguments是实参,方法名aaa, if ( firing ) { firingLength = list.length; } else if ( memory ) {//第一次没有赋值是undefined, firingStart = start; fire( memory ); } } return this; }, remove: function() { if ( list ) { jQuery.each( arguments, function( _, arg ) {//可以删除多个 var index; while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { list.splice( index, 1 );//删除 if ( firing ) { if ( index <= firingLength ) { firingLength--; } if ( index <= firingIndex ) { firingIndex--; } } } }); } return this; }, has: function( fn ) { return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); }, empty: function() { list = []; firingLength = 0; return this; }, disable: function() { list = stack = memory = undefined; return this; }, disabled: function() { return !list; }, lock: function() { stack = undefined; if ( !memory ) { self.disable(); } return this; }, locked: function() { return !stack; }, fireWith: function( context, args ) { if ( list && ( !fired || stack ) ) { args = args || []; args = [ context, args.slice ? args.slice() : args ]; if ( firing ) { stack.push( args ); } else { fire( args ); } } return this; }, fire: function() { self.fireWith( this, arguments );//cb.fire('hello'); return this; }, fired: function() { return !!fired; } }; return self; };