callbacks工具方法,作用是函数回调的统一管理 jQuery.Callbacks = function( options ) { } 使用:类似于事件绑定,fire之后,之前绑定的方法,都执行。 观察者模式。 function aaa() { alert(1); } function bbb() { alert(2); } function ccc() { alert(3) } var cb = $.Callbacks(); cb.add(aaa); cb.add(bbb); cb.add(ccc); cb.fire(); // 弹出了 1 和 2, 3 add(fun)-->List添加方法。 fire对list数组,进行for循环执行。 /**********************************************************/ function aaa() { alert(1); } (function () { function bbb() { alert(2); } })(); aaa(); bbb(); //这里无法同时执行弹出1 和 2,因为无法进行统一作用域的管 /**********************************************************/ // 但是Callbacks可以搞定,这个问题。 var cb = $.Callbacks(); function aaa() { alert(1); } cb.add(aaa); (function () { function bbb() { alert(2); } cb.add(bbb); })(); cb.fire(); // 只需要一句就可以了。触发所有 //这里只要回调对象时全局的, 就可以随时向回调函数中添加函数,而后执行。 /**********************************************************/ jQuery.Callbacks = function( options ) options配置参数。四个!!! * once: will ensure the callback list can only be fired once (like a Deferred) * * memory: will keep track of previous values and will call any callback added * after the list has been fired right away with the latest "memorized" * values (like a Deferred) * * unique: will ensure a callback can only be added once (no duplicate in the list) * * stopOnFalse: interrupt callings when a callback returns false Callbacks的四个参数。 var cb = $.Callbacks(); cb.fire(); cb.fire(); //fire可以执行多次触发的。 (1)once:代表,fire只能触发一次。 cb.fire(); cb.fire(); //不会执行。 让fire执行一次就好了 (2)memory: var cb = $.Callbacks(); function aaa() { alert(1); } cb.add(aaa); cb.fire(); function bbb() { alert(2); } cb.add(bbb); //这段代码执行过后,只能fire出1,不能执行bbb函数 var cb = $.Callbacks(‘memory‘); function aaa() { alert(1); } cb.add(aaa); cb.fire(); function bbb() { alert(2); } cb.add(bbb); //这段代码就是会打印出1 2 。后面的2也可以触发,只要添加就可以执行。 memory是作用到add上面,然后再调用fire。 var cb = $.Callbacks(‘memory‘); function aaa() { alert(1); return false; } cb.add(aaa); cb.fire(); function bbb() { alert(2); } setTimeout(function () { cb.add(bbb); }, 1000); 我想了一个例子,应该可以讲的明白,如果变量里面定义了memory,作为初始化, 那么,就执行。当你调用了fire以后,再向内添加add函数的时候,就直接继续执行。 (3)unique:去重复,让函数具有唯一性。作用于add var cb = $.Callbacks(); function aaa() { alert(1); } cb.add(aaa); cb.add(aaa); cb.fire(); //这里触发2次 var cb = $.Callbacks(‘unique‘); function aaa() { alert(1); } cb.add(aaa); cb.add(aaa); cb.fire(); //这里触发1次,重复的函数名,不能放入list, (4)stopOnFalse var cb = $.Callbacks(‘stopOnFalse‘); function aaa() { alert(1); return false; } cb.add(aaa); function bbb() { alert(2); } cb.add(bbb); cb.fire(); //这里只是执行了alert(1)。而alert(2),并没有背执行 //这个变量作用于fire中,判断函数中是否返回false,如果返回false,就立刻推出list循环。 当然还可以接受到组合的形式,比如,memory和once组合的形式,通过空格来分隔开的。 var cb = $.Callbacks(‘once stopOnFalse‘); Callbacks方法: add: 将函数,push入 list 中。 remove: 删除 has 检测是否有这个函数,返回false/true empty 清空数组 disable 全部锁住。禁止,不执行。 lock 锁住。stack=undefined locked 判断是否锁住 fireWith fire: --》调用的是fireWith. --》fire = function(data); fired 判断是否fired list = [], 用了保存函数列表。 add 添加。 add: function() { if ( list ) { // First, we save the current length var start = list.length; (function add( args ) { //这里支持传入多个,cb.add(aaa, bbb); jQuery.each( args, function( _, arg ) { var type = jQuery.type( arg ); if ( type === "function" ) { //判断是不是唯一。unique!!! if ( !options.unique || !self.has( arg ) ) { list.push( arg ); } } //支持数组形式, cb.add([aaa, bbb]); else if ( arg && arg.length && type !== "string" ) { // Inspect recursively add( arg ); } }); })( arguments ); // Do we need to add the callbacks to the // current firing batch? if ( firing ) { firingLength = list.length; //有merory就直接执行。 } else if ( memory ) { firingStart = start; fire( memory ); } } return this; }, 支持这个: cb.add(aaa); cb.add(aaa, bbb); cb.add([aaa, bbb]); remove:删除。 对数组进行遍历删除。splice 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; }, cb.add(aaa); cb.add(bbb); cb.add(ccc); cb.remove(bbb); cb.fire(); // 就只有aaa 和 ccc fire:执行。 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; //触发结束 if ( list ) { //判断list if ( stack ) { if ( stack.length ) { //stack的长度部位空, //递归调用 fire( stack.shift() ); //将栈中的第一个返回。并且fire } } //如果有记忆, else if ( memory ) { //列表清空 list = []; } else { self.disable(); } } }, //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 ]; if ( firing ) { stack.push( args ); } else { fire( 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 !!fired; } stack = !options.once && [], //这里定义了一个栈 firing 事件触发的时候。 fireWith: fireWith: function( context, args ) { if ( list && ( !fired || stack ) ) { args = args || []; args = [ context, args.slice ? args.slice() : args ]; //这里,如果是firing时,就讲fire压入栈 if ( firing ) { stack.push( args ); } else { fire( args ); } } return this; }, 有个例子 var cb = $.Callbacks(); var singal = true; function aaa() { alert(1); if (singal) { cb.fire(); //stack.push( args ); singal = false; } } cb.add(aaa); function bbb () { alert(2); } cb.add(bbb); cb.fire(); 弹出顺序是1,2 1,2. 这个是在fire中实现的。 if ( list ) { //判断list if ( stack ) { if ( stack.length ) { //stack的长度部位空, //递归调用 fire( stack.shift() ); //将栈中的第一个返回。并且fire } } //如果有memory的时候,就清空数组。 else if ( memory ) { //列表清空 list = []; } else { self.disable(); } }
原文:http://www.cnblogs.com/hgonlywj/p/4852964.html