脚本宝典收集整理的这篇文章主要介绍了javascript代码实例教程-jQuery.Callbacks源码解读,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。
一、源码解读
/*
* Create a callback list using the following parameters:
*
* options: an optional list of space-separated options that will change how
* the callback list behaves or a more tradITional option object
*
* By default a callback list will act like an event callback list and can be
* "fired" multiple times.
*
* Possible options:
*
* once: 确保回调列表仅只fire一次
will ensure the callback list can only be fired once (like a Deferred)
*
* memory: 在执行过fire后,保存之前fire时的参数,该参数会传递给在add中执行的最新添加的回调
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: 确保在add操作中,阻止存在回调列表中的回调再次被添加到回调列表中
will ensure a callback can only be added once (no duplicate in the list)
*
* stopOnFalse: 当正在执行的回调返回false,将中断其他未执行回调的执行
interrupt callings when a callback returns false
*
*/
VAR optionsCache = {},
// Used for splitting on whitespace
core_rnotwhite = //S+/g;
// Convert String-formatted options into Object-formatted ones and Store in cache
function createOptions( options ) {
// optionsCache[ options ] 用于缓存 object所引用的值
var object = optionsCache[ options ] = {};
jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
object[ flag ] = true;
});
return object;
}
jquery.Callbacks = function( options ) {
// Convert options From String-formatted to Object-formatted if needed
// (we check in cache First)
options = tyPEof options === "string" ?
// 只有当执行$.Callbacks(参数相同)二次及以上时,才不会执行createOptions函数
( optionsCache[ options ] || createOptions( options ) ) :
// 说明也可以这样$.Callbacks({once:true, memory:true})使用
jQuery.extend( {}, options );
var // Flag to know if list is currently firing
firing,
// Last fire value (for non-forgettable lists)
memory,
// Flag to know if list was already fired
fired,
// End of the loop when firing
firingLength,
// Index of currently firing callback (modified by remove if needed)
firingindex,
// First callback to fire (used internally by add and fireWith)
firingStart,
// Actual callback list
list = [],
// Stack of fire calls for repeatable lists
stack = !options.once && [],
// Fire callbacks
// data传递的是一个数组
// 使用Callbacks.fireWidth时,data包含fireWith函数传递的一个上下文环境和一个数组
// 使用Callbacks.fire时,data包含Callbacks对象和fire函数的arguments对象
fire = function( data ) {
// 如果options.memory为true,记录下data传递的数组
memory = options.memory && data;
fired = true;
// 如果options.memory为true,firingStart为上一次Callbacks.add后回调列表的length值
firingIndex = firingStart || 0;
// 重置firingStart为0
firingStart = 0;
firingLength = list.length;
firing = true;
for ( ; list && firingIndex < firingLength; firingIndex++ ) {
// 将data作为参数,执行回调列表中的所有回调
// 如果回调列表中其中一个回调返回false,且options.stopOnFalse为true,则中断接下来其他回调的执行
// 如果options.memory为true,将memory设置为false,阻止在Callbacks.add中新增回调的执行
if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
memory = false; // To PRevent further calls using add
break;
}
}
firing = false;
if ( list ) {
// 如果options.once为false
if ( stack ) {
// stack在fireWith操作时可能拥有成员
// 当stack拥有成员时(只有一个),并将其成员作为参数传递给将要执行的所有回调
if ( stack.length ) {
fire( stack.shift() );
}
}
// 如果options.memory为true且options.once为true,那么在add中执行一次fire(只执行最新添加的回调)
// 这里设置list = [],那么再次fire时,将不会有任何操作
else if ( memory ) {
list = [];
}
// 如果存在options.once为true,options.memory为false的其他情况,将禁用Callbacks对象
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 );
// 如果arg是一个函数
if ( type === "function" ) {
// arg为要新增到回调列表中的回调
// 如果arg不存在回调列表中,则将它增加到回调列表中
// 如果arg存在回调列表中,且options.unique为false,则将它增加到回调列表中
// 如果arg存在回调列表中,且options.unique为true,则不执行push动作
if ( !options.unique || !self.has( arg ) ) {
list.push( arg );
}
}
// 如果arg为数组或伪数组,则递归检查
else if ( arg && arg.length && type !== "string" ) {
// Inspect recursively
add( arg );
}
});
})( arguments );
// Do we need to add the callbacks to the
// current firing batch?
// 如果回调列表中的回调正在执行时,其中的一个回调函数执行了Callbacks.add操作
// 上句话可以简称:如果在执行Callbacks.add操作的状态为firing时
// 那么需要更新firingLength值
if ( firing ) {
firingLength = list.length;
// With memory, if we're not firing then
// we should call right away
// 如果options.memory为true,则将memory做为参数,应用最近增加的回调函数
} 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;
// 通过找到arguments成员在回调列表中索引位置遍历arguments对象,并将arguments成员从回调列表中移除
while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
list.splice( index, 1 );
// Handle firing indexes
// 如果在执行Callbacks.remove操作的状态为firing时
// 则更新firingLength和firingIndex的值
if ( firing ) {
if ( index <= firingLength ) {
firingLength--;
}
// 特殊处理,如果移除的回调的索引小于当前正在执行回调的索引,则firingIdex--
// 后面未执行的回调则得以正常执行
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.
// 检查fn是否存在回调列表中
has: function( fn ) {
return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
},
// Remove all callbacks from the list
// 清空回调列表中的所有回调
empty: function() {
list = [];
return this;
},
// Have the list do nothing anymore
// 禁用Callbacks对象
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 ) {
args = args || [];
args = [ context, args.slice ? args.slice() : args ];
if ( list && ( !fired || stack ) ) {
// 如果fired为true,options.once为false,且如果在执行fireWith操作的状态为firing
// 则将处理过的args作为stack数组的第一个数组项,并在firing为false后,将stack第一个数组项作为参数传递给将要执行的所有回调
// 如果fired为true,options.once为true,则不执行任何操作
// 可以看出,$.Callbacks('once')表示回调对象只fire一次
if ( firing ) {
stack.push( args );
}
// 第一次执行fireWith时,一定执行else分支
else {
fire( args );
}
}
return this;
},
// Call all the callbacks with the given arguments
// 将Callbacks对象,及Callbacks.fire函数中的arguments对象传递给Callbacks.fireWith函数,并执行
fire: function() {
self.fireWith( this, arguments );
return this;
},
// To know if the callbacks have already been called at least once
// 是否执行过fire函数
fired: function() {
return !!fired;
}
};
//返回Callbacks对象
return self;
};
二、jQuery.Callbacks内部中firing为true的实例
1、在Callbacks.add中firing为true的实例
$(function(){
// 定义三个将要增加到回调列表的回调函数fn1,fn2,fn3
function fn1(arg){
console.LOG( 'fn1 says:' + arg );
// 在fn1中执行Callbacks.add操作,此时Callbacks函数内部的firingLength将会得到更新
$callbacks.add(fn2);
}
function fn2(arg){
console.log( 'fn2 says:' + arg );
}
function fn3(arg){
console.log( 'fn3 says:' + arg );
}
// Callbacks传递了memory
// 也可以这样使用$.Callbacks({ memory: true });
var $callbacks = $.Callbacks('memory');
// 将fn1增加到回调列表中,因为在fn1中有执行了add(fn2)操作,因此回调列表中的回调为fn1,fn2
$callbacks.add(fn1);
// output: fn1 says:foo
// output: fn2 says:foo
$callbacks.fire('foo');
// 将之前fire的参数传递给最近增加的回调fn3,并执行fn3
// output: fn3 says:foo
$callbacks.add(fn3);
// 再执行一次fire,注意此时回调列表中的回调一次是fn1,fn2,fn3,fn2
// output: fn1 says:baz
// output: fn2 says:baz
// output: fn3 says:baz
// output: fn2 says:baz
// 如果期望回调列表中只有fn1,fn2,fn3,只需在Callbacks函数中传入unique
$callbacks.fire('baz');
});
2、在Callbacks.fireWith中firing为true的实例
$(function(){
function fn1(arg){
console.log( 'fn1 says:' + arg );
}
function fn2(arg){
console.log( 'fn2 says:' + arg );
$callbacks.fireWith(window, ['yjh']);
// 一定要执行这一步,否则将会陷入死循环
$callbacks.remove(fn2);
}
var $callbacks = $.Callbacks();
$callbacks.add(fn1);
// output: fn1 says:foo
$callbacks.fire('foo');
$callbacks.add(fn2);
// output: fn1 says:baz
// output: fn2 says:baz
// output: fn1 says:yjh
$callbacks.fire('baz');
});
觉得可用,就经常来吧! 脚本宝典 欢迎评论哦! js脚本,巧夺天工,精雕玉琢。小宝典献丑了!
以上是脚本宝典为你收集整理的javascript代码实例教程-jQuery.Callbacks源码解读全部内容,希望文章能够帮你解决javascript代码实例教程-jQuery.Callbacks源码解读所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。