var optionsCache = {};//这是jQuery.Callbacks 做的一个缓存变量
function createOptions( options ) {//这个方法会和jquery.callbacks方法结合使用,用于生成一个包含若干属性且值为真的对象
var object = optionsCache[ options ] = {};
jQuery.each( options.split( core_rspace ), function( _, flag ) {
object[ flag ] = true;
});
return object;
}
jQuery.Callbacks = function( options ) {//本对象接受四个字段中任意几个字段组成的字符串1,once每个方法只能执行一次2,memory会记录第一个执行的方法3,unique不支持重复方法4,stopOnFalse只要有一个方法返回false,则所有方法停止执行
options = typeof options === "string" ?
( optionsCache[ options ] || createOptions( options ) ) :
jQuery.extend( {}, options );//这一步保证返回一个对象,本对象包含指定属性的其中几个
var // Last fire value (for non-forgettable lists)
memory,//当前正在执行的作用域和传给每个方法的参数, 理解为内存,
fired,//是否执行
firing,//正在执行标记
firingStart,//执行的起始点
firingLength,//执行方法列表的总长度
firingIndex,//当前执行方法所处list数组的索引
list = [],//方法总列表
stack = !options.once && [],//如果每个方法只能执行一次就不向这个变量记录方法,这里面保存着未执行的作用域和参数,理解为队列
fire = function( data ) {//data[0]作用域, data[1]参数
memory = options.memory && data;//如果需要记录,则记录本次执行的作用域和参数
fired = true;//还未执行就可标记为已执行
firingIndex = firingStart || 0;//初始化执行的索引,可能是从firingStart开始执行的,因为list会动态的添加
firingStart = 0;//还原firingStart,备下次使用
firingLength = list.length;//计算list长度
firing = true;//正在执行标记
for ( ; list && firingIndex < firingLength; firingIndex++ ) {//遍历list并执行,
if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {//当stopOnFalse为真,只要有一个方法返回false,则执行中断
memory = false; // 执行失败则清除memory
break;
}
}
firing = false;//重置正在执行标记
if ( list ) {
if ( stack ) {//如果队列中有数据,则准备按顺序执行
if ( stack.length ) {
fire( stack.shift() );
}
} else if ( memory ) {//只把作用域和参数记录下来,防止后面加有新方法加进来时做默认值来用
list = [];//需要清空,否则第二次执行会再次执行
} else {
self.disable();
}
}
},
self = {
add: function() {//向全局变量list添加方法,参数个数随意
if ( list ) {
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 );
}
} else if ( arg && arg.length && type !== "string" ) {
add( arg );
}
});
})( arguments );
if ( firing ) {//如果正在执行,则修改正在执行的长度
firingLength = list.length;
} else if ( memory ) {//如果已执行完毕,并且已记录上次执行的作用域,则重新启动执行,否则不执行
firingStart = start;
fire( memory );
}
}
return this;
},
remove: function() {//移除某一个方法,并对其他相关变量做修改,
if ( list ) {
jQuery.each( arguments, function( _, arg ) {
var index;
while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
list.splice( index, 1 );
if ( firing ) {
if ( index <= firingLength ) {
firingLength--;
}
if ( index <= firingIndex ) {
firingIndex--;
}
}
}
});
}
return this;
},
has: function( fn ) {//判断一个方法是否已存在于List中
return jQuery.inArray( fn, list ) > -1;
},
empty: function() {//直接清空list
list = [];
return this;
},
disable: function() {直接中断执行
list = stack = memory = undefined;
return this;
},
disabled: function() {//判断是否已中断执行
return !list;
},
lock: function() {//锁定
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
},
locked: function() {//判断是否已锁定
return !stack;
},
fireWith: function( context, args ) {//参数一作用域, 参数二传给每个方法的参数集合
args = args || [];
args = [ context, args.slice ? args.slice() : args ];
if ( list && ( !fired || stack ) ) {//如果正在执行或者stack(队列)中有数据,则执行队列
if ( firing ) {
stack.push( args );
} else {//如果队列中有数据
fire( args );
}
}
return this;
},
fire: function() {//传入参数,然后以this为作用域开始执行方法链
self.fireWith( this, arguments );
return this;
},
fired: function() {//查看本方法链是否执行完毕
return !!fired;
}
};
return self;
};
Jquery.callbacks源码分析-jquery1.8.3
最新推荐文章于 2020-11-30 20:24:10 发布