jQuery callback源码分析

来源:互联网 发布:小夕kitty淘宝 编辑:程序博客网 时间:2024/06/07 05:50


self下的add()函数:

add: function() {if ( list ) {//当list为undefined时,不执行该if语句// First, we save the current lengthvar start = list.length;(function add( args ) {//此处args指对象argumentsjQuery.each( args, function( _, arg ) {var type = jQuery.type( arg );if ( type === "function" ) {//处理callbacks.add(函数A,函数B)的情况if ( !options.unique || !self.has( arg ) ) {list.push( arg );}} else if ( arg && arg.length && type !== "string" ) {//处理callbacks.add([函数A,函数B])的情况// Inspect recursivelyadd( arg );}});})( arguments );//对象arguments存放着add()函数中的参数// Do we need to add the callbacks to the// current firing batch?if ( firing ) {//如果在回调的函数中执行add,不管是不是$.Callbacks('memory'),都会执行添加的函数,例1firingLength = list.length;// With memory, if we're not firing then// we should call right away} else if ( memory ) {//如果不是在回调函数中执行add,并且$.Callbacks('memory'),则执行添加函数,例2//memory = options.memory && data; var callbacks = $.Callbacks('memory');则memory=datafiringStart = start;//start = list.length;fire( memory );}}return this;},

例1:如果在回调的函数中执行add,不管是不是$.Callbacks('memory'),都会执行添加的函数

var callbacks = $.Callbacks(); function aaa(){ alert(1); callbacks.add(bbb); } function bbb(){ alert(2) } callbacks.add(aaa); callbacks.fire();//会分别弹出1和2


例2:如果不是在回调函数中执行add,并且$.Callbacks('memory'),则执行添加函数

var callbacks = $.Callbacks('memory'); function aaa(){ alert(1); } function bbb(){ alert(2); } callbacks.add(aaa); callbacks.fire(); callbacks.add(bbb);

例3:callbacks.fire()中可以添加参数,参数将传递给回调函数,如callbacks.fire(123);

var callbacks = $.Callbacks(); function aaa(n){ alert(n); } callbacks.add(aaa); callbacks.fire(123);//弹出123


self下的remove():

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 indexesif ( firing ) {//在回调的过程中remove,即回调函数中有callbacks.remove(函数名),例4if ( index <= firingLength ) {firingLength--;//firingLength = list.length;}if ( index <= firingIndex ) {//如果删除的函数,在次函数之前,例5firingIndex--;//firingIndex表示正在执行的函数在list中的下标}}}});}return this;},


例4:在回调的过程中remove,即回调函数中有callbacks.remove(函数名)

var callbacks = $.Callbacks(); function a(){ console.log(1); } function b(){ console.log(2); callbacks.remove(c) } function c(){ console.log(3); } callbacks.add(a,b,c); callbacks.fire();//1 2 执行函数b()后,已经把函数c()删除了

例5:在回调的过程中remove,并且删除的函数,在次函数之前

var callbacks = $.Callbacks(); function a(){ console.log(1); } function b(){ console.log(2); callbacks.remove(a) } function c(){ console.log(3); } callbacks.add(a,b,c); callbacks.fire();//1 2 3 callbacks.fire();//2 3

self下的lock():

lock: function() {stack = undefined;if ( !memory ) {//当还没有执行过私有方法fire()时,memory的值时undefined。例7self.disable();}return this;},
例6:执行过私有函数fire()后,fired=true,再执行callbacks.lock()后,只是不能调用不能通过fireWith()调用私有函数fire(),因为if ( list && ( !fired || stack ) )相当于if(false),但是还可以通过add()函数中调用私有函数fire(),调用的前提:

var callbacks = $.Callbacks('memory');并且在add()之前执行过私有函数fire(),

因为私有函数fire()未执行时,变量memory时undefined,执行过fire()后,memory = options.memory && data;即options.memory必须为true,add()才会调用私有函数fire()

var callbacks = $.Callbacks('memory');   function a(){   console.log(1);   }   function b(){   console.log(2);   }   function c(){   console.log(3);   }   callbacks.add(a);   callbacks.fire();//1   callbacks.lock();   callbacks.add(b);//2   callbacks.add(c);//3   callbacks.fire();

例7:当还没有执行过私有方法fire()时,变量memory为undefined,此时执行执行callbacks.lock(),就是执行

self.disable()

disable: function() {list = stack = memory = undefined;return this;},
执行disable()后fireWith()中的if ( list && ( !fired || stack ) )相当于if(false),虽然( !fired || stack )为true,但是list=undefined,也不能执行add()操作,因为list=undefined,不能执行list.push( arg ),
var callbacks = $.Callbacks('memory');   function a(){   console.log(1);   }   callbacks.lock();   callbacks.add(a);//没有结果   callbacks.fire();//没有结果

lock()和disable()的区别:

调用私有函数fire()有两种渠道:

通过fireWith()调用私有函数fire(),只要if ( list && ( !fired || stack ) )为真;

通过add()函数中调用私有函数fire(),调用的前提:var callbacks = $.Callbacks('memory');并且在add()之前执行过私有函数fire(),因为私有函数fire()未执行时,变量memory时undefined,执行过fire()后,memory = options.memory && data;即options.memory必须为true,add()才会调用私有函数fire()。

当执行过私有函数fire()后,lock()函数没有限制add()函数中调用私有函数fire()。

lock()函数将禁止使用callbacks.fire():在callbacks.fire()之前调用callbacks.lock(),此时memory是undefined,相当于调用了disable(),callbacks.fire()之后调用callbacks.lock(),( !fired || stack )是false,callbacks.fire()禁止使用,

总之,callbacks.lock()出现后,callbacks.fire()都会作废

lock: function() {stack = undefined;if ( !memory ) {self.disable();}return this;},


self下的fire()和fireWith():

参数once的作用体现:

stack = !options.once && [],

当$.Callbacks('once')时,stack=false,

callbacks.fire()

callbacks.fire()有两个时只能触发一次因为第一个callbacks.fire()执行后,fired=true,( !fired || stack )值是false

fireWith()就不能调用fire()。

在回调函数中执行callbacks.fire(),先不调用私有函数fire(),先将上下文和参数push到stack数组中,私有函数fire中发现,数组stack有内容,则将内容取出,作为fire()的参数,并执行fire()

fire: function() {self.fireWith( this, arguments );return this;},
fireWith: function( context, args ) {if ( list && ( !fired || stack ) ) {//1.当list为undefined时,直接返回this//2.如果执行过callbacks.fire(),并且stack = undefined,直接返回this//但是在add()函数中,当memory为真时,可以调用fire()args = args || [];args = [ context, args.slice ? args.slice() : args ];if ( firing ) {//在回调函数中执行callbacks.fire(),先不调用私有函数fire()。例8stack.push( args );} else {fire( args );}}return this;},

私有函数fire():

fire = function( data ) {memory = options.memory && data;fired = true;firingIndex = firingStart || 0;firingStart = 0;firingLength = list.length;firing = true;//当list为undefined时,不能执行for循环语句,也就不能执行回调函数for ( ; list && firingIndex < firingLength; firingIndex++ ) {//data[ 1 ]表示callbacks.fire(123)中的参数123,此参数将作为回调函数的参数if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {memory = false; // To prevent further calls using addbreak;}}firing = false;if ( list ) {//当list为undefined时,不进一下行任何操作if ( stack ) {//var callbacks = $.Callbacks('不是once');if ( stack.length ) {fire( stack.shift() );}} else if ( memory ) {//var callbacks = $.Callbacks('once memory');list = [];} else {//var callbacks = $.Callbacks('once');self.disable();}}},

例8:结果是无限循环输出1, 2 ,1 ,2...,而不是1 ,1 ,1...

var callbacks = $.Callbacks();   function a(){   console.log(1);   }   function b(){   callbacks.fire();   console.log(2);   }   callbacks.add(a,b);   callbacks.fire();

如果想要只循环一次,则需要设置一个开关:

var oBtn = true;var callbacks = $.Callbacks();   function a(){   console.log(1);   }   function b(){   if(oBtn){   callbacks.fire();   oBtn = false;   }   console.log(2);   }   callbacks.add(a,b);   callbacks.fire();//1,2,1,2







原创粉丝点击