回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
// 工具函数,将字符串格式的标记转换为对象格式,并把转换结果缓存起来
function createFlags( flags ) {
//初始化返回值object和flagsCache[flags]为空对象,同时指向了同一个空对象,当变量object添加属性时也是在为flagsCache[flags]添加属性,不需要要再写一行代码把变量object放入缓存对象flagsCache中了
var object = flagsCache[ flags ] = {},
i, length;
flags = flags.split( /\s+/ ); //用空白符把标记字符串分割为数组
//遍历数组,为返回值object添加单个标记,属性值为true,最后返回对象
for ( i = 0, length = flags.length; i < length; i++ ) {
object[ flags[i] ] = true;
}
return object;
}
jQuery.Callbacks = function( flags ) {
// 解析字符串标记为flags为对象,先从缓存对象flagsCache中获取标记字符串flags对应的标记对象,如果没有找到,在调用工具函数createFlags(flags)将标记字符串flags解析为标记对象,并放入寒碜对象flagsCache中
flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
var // 声明局部变量,通过闭包机制引用
list = [],//存放回调函数的数组
//在可重复触发、正在执行的列表上,重复触发时,将上下文和参数放入数组stack中
stack = [],
memory,
//
fired,
// 回调函数列表是否正在执行中
firing,
// 待执行的第一个回调函数的下标
firingStart,
// End of the loop when firing
firingLength,
// Index of currently firing callback (modified by remove if needed)
firingIndex,
// 添加回调函数的工具函数
add = function( args ) {
var i,
length,
elem,
type,
actual;
//遍历参数args,把回调函数逐个添加到数组list中,
for ( i = 0, length = args.length; i < length; i++ ) {
elem = args[ i ];
type = jQuery.type( elem );
//判断args[i]类型,如果是数组,则迭代调用规矩函数add(args)把数组中的回调函数添加到数组list中,
if ( type === "array" ) {
add( elem );
} else if ( type === "function" ) {
// 如果是函数且不是unique模式,或者是unique模式但未添加过,才会添加args[i]到数组中list中
if ( !flags.unique || !self.has( elem ) ) {
list.push( elem );
}
}
}
},
// 触发回调函数的工具函数,使用上下文context和参数args调用数组list中的回调函数,该回调函数通过闭包机制引用数组list
//参数context用于指定回调函数执行时的上下文,即关键字this所引用的对象,参数args用于指定调用回调函数时传入的参数
fire = function( context, args ) {
args = args || [];
//若当前回调函数列表不是memory模式,则变量memory则被赋值为true,间接地表示当前回调函数列表已经被触发过
memory = !flags.memory || [ context, args ];
fired = true;
firing = true;
firingIndex = firingStart || 0;
firingStart = 0;
firingLength = list.length;
for ( ; list && firingIndex < firingLength; firingIndex++ ) {
//执行回调函数list[ firingIndex ],如果返回值是false,且当前回调函数列表是stopOnFalse模式,则变量memory被赋值为true,并停止执行后续的其他回调函数,
if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
memory = true; // Mark as halted
break;
}
}
firing = false;
if ( list ) {
//如果不是once模式,即可以多次触发回调函数列表,则从变量stack中弹出存放的下文和参数,再次执行整个回调函数列表,直到stack为空
if ( !flags.once ) {
if ( stack && stack.length ) {
memory = stack.shift();
self.fireWith( memory[ 0 ], memory[ 1 ] );
}
} else if ( memory === true ) {
self.disable();
} else {
list = [];
}
}
},
// 回调函数列表,方法jQuery.Callbacks(flags)的返回值
self = {
// 添加回调函数
add: function() {
if ( list ) {
//先备份数组list长度
var length = list.length;
add( arguments );
// 如果回调函数正在执行,修正结束下标firingLength,使得新添加的回调函数也得以执行
if ( firing ) {
firingLength = list.length;
//
} else if ( memory && memory !== true ) {
firingStart = length;
fire( memory[ 0 ], memory[ 1 ] );
}
}
return this;
},
// 移除回调函数,从回调函数列表中移除一个或一组回调函数,移除前修正结束下标firingLength和当前下班firingIndex
remove: function() {
if ( list ) {
var args = arguments,
argIndex = 0,
argLength = args.length;
//遍历待移除的回调函数数组,在循环体内嵌套遍历已有的回调函数数组,
for ( ; argIndex < argLength ; argIndex++ ) {
for ( var i = 0; i < list.length; i++ ) {
//如果检查到某个待移除回调函数与某个已有的回调函数完全相等,则从已有的回调函数数组中移除它
if ( args[ argIndex ] === list[ i ] ) {
// 回调函数是否在列表中
if ( firing ) {
//如果回调函数列表正在执行 if ( i <= firingLength ) {
//在移除前使用结束下标firingLength减1 firingLength--;
//如果待移除函数的下标小于正在执行回调函数的下标firingIndex,即待移除的回调函数已经执行,则修正firingIndex减1,以确保不会漏执行回调函数 if ( i <= firingIndex ) {
firingIndex--;
}
}
}
// 调用数组原型方法splice(),从匹配下标处开始移除1个元素,循环变量i自减一,修正为下一个回调函数的下标
list.splice( i--, 1 );
/
// 在unique模式下,数组list中不会有重复的回调函数,可以直接退出内层遍历,针对unique模式做的优化
if ( flags.unique ) {
break;
}
}
}
}
}
return this;
},
// 回调函数是都在列表中
has: function( fn ) {
if ( list ) {
var i = 0,
length = list.length;
for ( ; i < length; i++ ) {
if ( fn === list[ i ] ) {
return true;
}
}
}
return false;
},
// 清空列表
empty: function() {
list = [];
return this;
},
// 禁用列表
disable: function() {
list = stack = memory = undefined;
return this;
},
// 是否已禁用列表
disabled: function() {
return !list;
},
// 锁定列表
lock: function() {
stack = undefined;
if ( !memory || memory === true ) {
self.disable();
}
return this;
},
// 是否已错定列表
locked: function() {
return !stack;
},
// 使用指定的上下文和参数调用回调函数
fireWith: function( context, args ) {
if ( stack ) {
if ( firing ) {
if ( !flags.once ) {
stack.push( [ context, args ] );
}
} else if ( !( flags.once && memory ) ) {
fire( context, args );
}
}
return this;
},
// 使用指定的参数调用回调函数,上下文为self
fire: function() {
self.fireWith( this, arguments );
return this;
},
// 回调函数列表是否至少执行过一次
fired: function() {
return !!fired;
}
};
return self;
};
时间: 2024-11-02 14:54:15