JQ的回调对象处理,通过回调对象管理函数 对函数的统一管理
// 类似于绑定事件
function aa(){
console.log(1);
}
function bb(){
console.log(2);
}
var cb = $.Callbacks();
cb.add(aa, bb);
cb.fire();
function aaa() {
alert(1);
}
cb.add(aaa);
(function () {
function bbb() {
alert(2);
}
cb.add(bbb);
})();
// 外部直接调用bbb()无法实现
cb.fire(); // 弹出1 2
jQuery.Callbacks = function(options){}中几个参数的作用
once
:执行几次cb.fire(),列表里的方法也会执行几次,在定义的时候加上once参数var cb = $.Callbacks('once'),让cb.fire()只能执行一次,可避免cb.fire()多次执行。once是作用到函数列表上的,保证循环的时候只循环一次。
memory
:cb.add(aaa); cb.fire(); cb.add(bbb); 按顺序执行的时候由于bbb是后添加的,因此只有aaa被执行了,var cb = $.Callbacks('memory')的作用是添加完方法直接就调用fire来执行这个方法,这时候bbb也会被执行。memory式作用在add方法上的,添加完再作用到fire上。
unique
:去重,多次添加同一个函数,会在内部去重,同样是作用在add方法上。
stopOnFalse
:如果添加的函数在执行过程中返回值为false,后续添加的函数不会再执行。作用到list循环也就是fire方法上。
四个参数可以组合,用空格分开,例如var cb = $.Callbacks('once memory')
一个函数可以做很多不同的事情,例如判断当前方法在不在list集合里面的时候,若传一个方法进去就用inArray判断在不在,不传的时候就判断这个list有没有
has: function( fn ) {
return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
}
disable和lock的区别:
disable为阻止后续一切的操作,list,stack,memory都置为undefined
lock是锁住stack,将他置为undefined,而stack是用来控制fire执行次数的,所以lock之后再调用fire就无法执行。
// JQ的回调对象处理,通过回调对象管理函数 对函数的统一管理
jQuery.Callbacks = function( options ) {
// Convert options from String-formatted to Object-formatted if needed
// (we check in cache first)
options = typeof options === "string" ?
( optionsCache[ options ] || createOptions( options ) ) :
jQuery.extend( {}, options );
var // Last fire value (for non-forgettable lists)
memory,
// Flag to know if list was already fired
fired,
// Flag to know if list is currently firing
firing,
// First callback to fire (used internally by add and fireWith)
firingStart,
// End of the loop when firing
firingLength,
// Index of currently firing callback (modified by remove if needed)
firingIndex,
// Actual callback list
// 存函数的集合
list = [],
// Stack of fire calls for repeatable lists
stack = !options.once && [],
// Fire callbacks
// for循环函数的list集合
fire = function( data ) {
memory = options.memory && data;
fired = true;
firingIndex = firingStart || 0;
firingStart = 0;
firingLength = list.length;
firing = true;
for ( ; list && firingIndex < firingLength; firingIndex++ ) {
// data[1]就是通过fire传的参数
if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false
&& options.stopOnFalse ) {
memory = false; // To prevent further calls using add
break;
}
}
firing = false;
if ( list ) {
if ( stack ) {
if ( stack.length ) {
fire( stack.shift() );
}
// stack为false 即once为1 只执行一次,完了之后就清空
} else if ( memory ) {
list = [];
} else {
self.disable();
}
}
},
// Actual Callbacks object
self = {
// Add a callback or a collection of callbacks to the list
add: function() {
if ( list ) {
// First, we save the current length
var start = list.length;
(function add( args ) {
jQuery.each( args, function( _, arg ) {
var type = jQuery.type( arg );
// 以方法名的形式添加
if ( type === "function" ) {
if ( !options.unique || !self.has( arg ) ) {
list.push( arg );
}
// 以数组的形式添加函数 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;
// With memory, if we're not firing then
// we should call right away
} else if ( memory ) {
firingStart = start;
fire( memory );
}
}
return this;
},
// Remove a callback from the list
remove: function() {
if ( list ) {
jQuery.each( arguments, function( _, arg ) {
var index;
// 用splice删除当前
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;
},
// Check if a given callback is in the list.
// If no argument is given, return whether or not list has callbacks attached.
has: function( fn ) {
return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
},
// Remove all callbacks from the list
empty: function() {
list = [];
firingLength = 0;
return this;
},
// Have the list do nothing anymore
disable: function() {
list = stack = memory = undefined;
return this;
},
// Is it disabled?
disabled: function() {
return !list;
},
// Lock the list in its current state
lock: function() {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
},
// Is it locked?
locked: function() {
return !stack;
},
// Call all callbacks with the given context and arguments
fireWith: function( context, args ) {
if ( list && ( !fired || stack ) ) {
// fire支持传参 (可以传递给list集合里面的方法)
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;
}
};
return self;
};
网友评论