jQuery 源码callbacks

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();
				}
			}
时间: 2024-08-07 16:43:02

jQuery 源码callbacks的相关文章

jQuery源码解读第5章---对Callbacks的解读

jQuery.Callbacks() 是一个多用途的回调函数列表对象 提供了一种强大的方法来管理回调函数队列 先来看看Callbacks的常见的用法 1-------不带参数 先看看不用回调函数的例子 eq function a1(){ console.log('a1') } (function(){ function a2(){ console.log('a2') } })() a1() // a1 a2() //就不行了 这时候我们就可以使用回调函数Callbacks 了 var dfd1

读jQuery源码之四(Callbacks,Deferred,when)

看了下Sizzle部分源码,核心的原理就是使用正则表达式去匹配,找到对应的原生获取元素的方法,我没有去细究了.大家有兴趣可以自己看看,分享分享! 从2850行开始,继续往下读jQuery源码(2850-3043行) 进入Callbacks(回调函数管理模块)之前,有几个扩展方法 1.dir方法 三个参数:elem——dom元素,dir——指定elem的层级名称(例如parentNode,nextSibling),until——结束判断.返回一个数组,比如获取某个元素的parentNode,如果不

jquery源码 Callback

工具方法.对函数的统一管理. jquery2.0.3版本$.Callback()部分的源码如下: // String to Object options format cache var optionsCache = {}; // Convert String-formatted options into Object-formatted ones and store in cache function createOptions( options ) { var object = option

jquery源码分析(二)——结构

再来复习下整体架构: jQuery源码分析(基于 jQuery 1.11 版本,共计8829行源码) (21,94)                定义了一些变量和函数jQuery=function(){} (96,280)        给jQuery添加一些方法和属性,jQuery.fn=jQuery.prototype(285,347)        extend:        jQuery的一些继承方法        更容易进行后续的扩展                       

jQuery源码分析-jQuery中的循环技巧

Js代码   作者:nuysoft/JS攻城师/高云 QQ:47214707 EMail:[email protected] 声明:本文为原创文章,如需转载,请注明来源并保留原文链接. 前记:本文收集了jQuery中出现的各种遍历技巧和场景 Js代码   // 简单的for-in(事件) for ( type in events ) { } Js代码   // 缓存length属性,避免每次都去查找length属性,稍微提升遍历速度 // 但是如果遍历HTMLCollection时,性能提升非常

jQuery源码分析系列(38) : 队列操作

Queue队列,如同data数据缓存与Deferred异步模型一样,都是jQuery库的内部实现的基础设施 Queue队列是animate动画依赖的基础设施,整个jQuery中队列仅供给动画使用 Queue队列 队列是一种特殊的线性表,只允许在表的前端(队头)进行删除操作(出队),在表的后端(队尾)进行插入操作(入队).队列的特点是先进先出(FIFO-first in first out),即最先插入的元素最先被删除. 为什么要引入队列? 我们知道代码的执行流有异步与同步之分,例如 var a

jQuery源码解读第4章---对extend的解读

为什么我们一开始就说extend呢 其实我读源码的过程中,发现其实我们方法就在源码中都调用了extend Callbacks Deferred这些工具方法 所以我们很有必要先学习这些,,,,,,,,,,,这样对我们后续的学习很有帮助 对extend的学习,,,,,首先看下extend我们平时是怎么用的 1...合并对象 extend(dest,src1,src2,,,,,) 它的含义就是将src1,src2......合并到dest中 然后放回的结果就是合并后的dest eq: var dest

jQuery源码框架思路

开始计划时间读源码,第一节jQuery框架阅读思路整理 (function(){ jQuery = function(){}; jQuery一些变量和函数和给jQuery对象添加一些方法和属性 extend : jQuery的继承方法的实现 jQuery.extend() : 使用jQuery扩展一些工具方法 Sizzle : jQuery自身实现的复杂选择器 Callbacks : 回调函数 Deferred : 延迟对象(异步) support : 功能检测(嗅探) data() : 数据缓

jquery源码解析:代码结构分析

本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94)     定义了一些变量和函数,   jQuery = function(){}; (96,283)   给jQuery对象添加一些属性和方法(实例方法,通过$("div")这类的jQuery实例对象来调用) (285,347)   extend : jQuery的继承方法 (349,817)   jQuery.extend():扩展一些工具方法(静态方法,直接通