var callbacks = $.Callbacks("once");
callbacks.add(function(){console.log("f1");});
callbacks.fire(); //输出 "f1"
callbacks.fire(); //什么也不发生,在源码中已经禁用了 list.disable()
$(function($){
var callbacks = $.Callbacks("memory");
callbacks.add(function(){console.log("f1");});
callbacks.fire(); //输出 "f1",这时函数列表已经执行完毕!
callbacks.add(function(){console.log("f2");}); //memory作用在这里,没有fire,一样有结果: f2
callbacks.fire(); //重新触发一次,输出 f1 f2。 firingStart = 0
//与once一起使用
callbacks = $.Callbacks("once memory");
callbacks.add(function(){console.log("f3");});
callbacks.fire(); //输出 "f3",这时函数列表已经执行完毕!
callbacks.add(function(){console.log("f4");}); //没有fire,一样有结果: f4
callbacks.fire(); //由于为"once",这里将什么也不执行
});
var f1 = function(){console.log("f1");};
var callbacks = $.Callbacks();
callbacks.add(f1);
callbacks.add(f1);
callbacks.fire(); //输出 f1 f1
//传递参数 "unique"
callbacks = $.Callbacks("unique");
callbacks.add(f1); //有效
callbacks.add(f1); //添加不进去
callbacks.fire(); //输出: f1
var f1 = function(){console.log("f1"); return false}; //注意 return false;
var f2 = function(){console.log("f2");};
var callbacks = $.Callbacks();
callbacks.add(f1);
callbacks.add(f2);
callbacks.fire(); //输出 f1 f2
callbacks = $.Callbacks("memory stopOnFalse");
callbacks.add(f1);
callbacks.add(f2);
callbacks.fire(); //只输出 f1
callbacks.add(function(){console.log("f3");}); //不会输出,memory已经失去作用了
callbacks.fire(); //重新触发,输出f1
var i = 0;
var inc = function (s){
i++;
alert(i +"$" + s);
};
var callbacks = $.Callbacks('memory');
callbacks.add(function iteral() {
callbacks.add(inc);
if (i <= 1) {
callbacks.fire(i);
}
});
callbacks.fire(i);
callbacks.add(inc);
/*
list = [];
list = [it];
--->fire(0), i=0
1、list = [it, inc]
2、push(fire(0))
3、i++ [inc(0)] (i=1)
shift()--->fire(0), i=1
1、list = [it, inc, inc];
2、push(fire(1)),
3、i++ [inc(0)]
4、i++ [inc(0)] (i=3)
shift()--->fire(1),i=3
1、list = [it, inc, inc, inc];
2、i++ [inc(1)]
3、i++ [inc(1)]
4、i++ [inc(1)] (i=6)
--->add(inc), i=6, memory=[this,1]
1、i++ [inc(1)] (i=7)
*/
jQuery.Callbacks = function (options) {
// string --> object 改进建议:将未配置的参数缺省为false,而不是undefined。便于程序阅读和控制.
options = optionsCache[options] || createOptions(options);
var firing,
memory, //Last fire value [context, args] (for memory lists)
fired,
firingLength,
firingIndex,
firingStart,
list = [],
stack = options.once === true ? false : [], // Stack of fire calls for repeatable lists
fire = function (data) { // data --> [context, args]
memory = !!options.memory && data; // false OR [context, arguments]
fired = true;
firingIndex = firingStart || 0;
firingStart = 0;
firingLength = list.length;
firing = true;
// 这里 list 放在条件判断中是因为执行回调函数可能会改变 list 的状态,比如 this.disable()。
for ( ; list && firingIndex < firingLength; firingIndex++) {
if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse === true) {
memory = false; // 禁止 memory 功能,这样调用 add() 增加新回调函数不会立即自动调用
break;
}
}
firing = false;
if (list) {
if (stack) {
//进入条件: fired && firing === false && stack, 实现递归调用
if (stack.length) {
fire(stack.shift()); // [[context1, arguments1], [context2, arguments2]]
}
} else if (memory) {
// 进入条件: fired && firing === false && stack === undefined && 有memory字段(memory变量只能通过fire()函数修改)
// 这里的 list = [],主要是用于性能优化,以防该对象长时间不执行,占用系统内存
list = [];
} else {
// 进入条件: fired && firing === false && stack === undefined && 没有memory字段, 说明必要继续保留的必要
self.disable();
}
}
},
self = {
add: function() {
if (list) { //几乎所有API都应该绑定这个条件,因为我们需要处理队列
var originLength = list.length;
jQuery.each(arguments, function( _, arg) {
if (jQuery.type(arg) === "function") {
// (!(options.unique && self.has(arg))) unique字段的作用
if (!options.unique || !self.has(arg)) {
list.push(arg);
}
}
});
if (firing === true) {
// 进入条件: 说明正在执行回调函数队列中,而当前执行的这个回调函数激活了add()函数,及时维护循环边界
firingLength = list.length;
} else if (memory) {
// 进入条件: memory && fired && firing === false, 说明之前的 fire() 行为已经完全结束
firingStart = originLength;
fire(memory);
}
}
return this;
},
remove: function() {
if (list) {
jQuery.each(arguments, function( _, arg) {
var lastIndex;
while ((lastIndex = jQuery.inArray(arg, list, lastIndex)) >= 0) {
list.splice(lastIndex, 1);
if (firing === true) { // 及时更新边界条件,实现智能处理
if (lastIndex <= firingLength) {
firingLength--;
}
if (lastIndex <= firingIndex) {
firingIndex--;
}
}
}
});
}
return this;
},
has: function (func) { //这个API有两个功能,根据单一职责角度来说,应该增加一个 isNotEmpty() 接口(非空)
return func ? jQuery.inArray(func, list) > -1 : !!(list && list.length);
},
empty: function() {
list = [];
return this;
},
disable: function() { // 彻底禁用该对象, stack禁用, memory禁用
list = stack = memory = undefined;
return this;
},
disabled: function() {
return !list;
},
lock: function() {
stack = undefined;
// 如果memory没有存储调用状态,直接禁用这个对象(可能是从未调用就被锁定,或者没有memory字段)
if (!memory) {
self.disable();
}
return this;
},
locked: function() {
return !stack;
},
fireWith: function (context, args) {
args = args || [];
var data = [context, args];
if (list && (fired === false || stack) ) {
if (firing) {
// 进入条件: firing === true && stack 说明当前正在执行回调函数队列
stack.push(data); // stack其实是一个队列结构,这里用 stack 有些混淆
} else {
// 进入条件一: firing === false && fired === false 说明从来没有 fire()过
// 进入条件二: firing === false && fired === true && stack = [] 说明至少调用过一次,而且当前允许多次调用,可以通过lock()锁定
fire(args);
}
}
return this;
},
fire: function() {
self.fireWith(this, arguments);
return this;
},
fired: function() {
return !!fired;
}
};
return self;
};
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有