jQuery.callbacks 注释
(function( jQuery ) {
// String to Object flags format cache
var flagsCache = {};
// Convert String-formatted flags into Object-formatted ones and store in cache
// 将字符串形式的flags转换成对象形式,并且存到cache中,例: "once memory" => {"once":true,"memory":true}
function createFlags( flags ) {
var object = flagsCache[ flags ] = {},
i, length;
flags = flags.split( /\s+/ );
for ( i = , length = flags.length; i < length; i++ ) {
object[ flags[i] ] = true;
}
return object;
}
/*
* 用以下参数创建一个回调函数列表:
*
* flags: 可选的以空格分隔的flags,会影响回调函数列表的行为
*
*
* 默认情况下,回调函数列表的行为如同一个事件回调函数列表一样,并且可以触发多次。
*
* 可选的 flags:
*
* once: 会确保回调列表只被触发一次(像Deferred一样), 这个不会阻止memory模式,也就是说 "once memory"的参数下 虽然只能fire一次,但是fire后再add 还是有效果的
*
* memory: 会记录上一次fire的上下文(一般是$.callbacks自身)和参数,并且会立即以最近一次fire记录下的上下文和参数执行新添加进来回调函数 (像Deferred一样)
* 具体看 (1) 88行 memory = !flags.memory || [ context, args ]; 保存memory模式下的 函数上下文和参数
* (2) 127-130行 self.add添加回调函数时候的处理
*
* unique: 会确同一个回调函数只在列表中出现一次
*
* stopOnFalse: 其中一个回调函数返回false即停止调用其余函数
*
*/
jQuery.Callbacks = function( flags ) {
// Convert flags from String-formatted to Object-formatted
// (we check in cache first)
flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
var // 实际存放回调函数的容器
list = [],
// 用以存放可重复fire(即非once模式),重复fire的回调函数 例: 在一个回调函数体里边也调用了fire的情景
// 另外这个stack 还用以标示整个回调列表是否处于锁定状态(仅仅判可不可触发fire, 还是可以add, remove的) 205行 + 192-202行
stack = [],
// 上次fire的上下文和参数,
// 可能的值: (1) [context,args]
// (2) true , 非记忆执行上下文和参数 或者 stopOnFalse模式下有返回为false的回调函数
memory,
// 标识当前是否处于fire状态
firing,
// fire第一个执行的回调函数在list中的索引位置 (内部fireWith使用和add导致list个数变化时修正执行中的索引位置 128行)
firingStart,
// 循环的结尾位置 (如果在firing状态下self.add添加新函数和self.remove移除函数时候会调整 123行 146行 )
firingLength,
// 当前触发的函数索引 ,需要的时候会调整
firingIndex,
//工具方法: 添加一个或多个(args为数组时)函数到list
add = function( args ) {
var i,
length,
elem,
type,
actual;
for ( i = , length = args.length; i < length; i++ ) {
elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
// 递归检查
add( elem );
} else if ( type === "function" ) {
// 非unique模式且新回调函数不存在
if ( !flags.unique || !self.has( elem ) ) {
list.push( elem );
}
}
}
},
//工具方法: 触发回调函数
fire = function( context, args ) {
args = args || [];
memory = !flags.memory || [ context, args ];
firing = true;
firingIndex = firingStart || ;
firingStart = ;
firingLength = list.length;
for ( ; list && firingIndex < firingLength; firingIndex++ ) {
if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
memory = true; // 标记为终止 注意看106行, 销毁$.callbacks
break;
}
}
firing = false; // 标记执行结束
if ( list ) {
if ( !flags.once ) { // fire完后检查是否有回调函数内部重复fire保留下来的执行上下文和参数
if ( stack && stack.length ) {
memory = stack.shift();
self.fireWith( memory[ ], memory[ ] );
}
} else if ( memory === true ) { // stopOnFalse
self.disable();
} else {
list = [];
}
}
},
// 实际的回调函数对象
self = {
//实例方法: 添加一个或多个(args为数组时)函数到list
add: function() {
if ( list ) {
var length = list.length;
add( 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, unless previous
// firing was halted (stopOnFalse)
} else if ( memory && memory !== true ) {
firingStart = length;
fire( memory[ ], memory[ ] );
}
}
return this;
},
// 从列表中移除函数
remove: function() {
if ( list ) {
var args = arguments,
argIndex = ,
argLength = args.length;
for ( ; argIndex < argLength ; argIndex++ ) {
for ( var i = ; i < list.length; i++ ) {
if ( args[ argIndex ] === list[ i ] ) {
// 在firing时移除函数,需要修正当前索引firingIndex和长度firingLength
if ( firing ) {
if ( i <= firingLength ) {
firingLength--;
if ( i <= firingIndex ) {
firingIndex--;
}
}
}
// Remove the element
list.splice( i--, );
// 如果是unique模式(这时不会有重复的函数),移除一次就可以了
if ( flags.unique ) {
break;
}
}
}
}
}
return this;
},
// 判断指定回调函数是否存在
has: function( fn ) {
if ( list ) {
var i = ,
length = list.length;
for ( ; i < length; i++ ) {
if ( fn === list[ i ] ) {
return true;
}
}
}
return false;
},
// Remove all callbacks from the list
empty: function() {
list = [];
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 || memory === true ) {
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 ( stack ) { // stack=[] 也是true
if ( firing ) {
if ( !flags.once ) {
stack.push( [ context, args ] );
}
} else if ( !( flags.once && memory ) ) {
fire( context, 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 !!memory; // 其实这个有问题, 当调用disable() 的时候 memory==undefined
}
};
return self;
};
})( jQuery );
下面是一些检验这些参数逻辑的代码:
/*
jquery.Callbacks
*/
// var testUrl="http://www.runoob.com/try/ajax/demo_test.php";
// var callbacks=new jQuery.Callbacks("memory");
// callbacks.add(function(){alert("first callback")});
// callbacks.add(function(){alert("second callback")});
// callbacks.fire();
// memory
// callbacks.add(function(){alert("third callback")}); var callback2=
jQuery.Callbacks("once memory"), // once 表示回调函数列表只会fire一次,但是还会运行memory机制,也不限制回调函数列表里边有多个相同的函数(可以用unique 去重)
something = true;
function fn1(args)
{
alert('fn1 args:'+args);
console.log(this);
if(something){
callback2.fire(" test:第2次触发");
callback2.fire(" test:第3次触发"); //fire内部再触发的话 先放入stack中
something=false;
}
}
function fn2(){
alert('fn2');
}
callback2.add(fn1);
callback2.add(fn2); callback2.fire('测试:第1次触发');
callback2.fire('测试:第4次触发'); //once模式 只会fire一次, memory在add的时候促发
callback2.add(fn2);
jQuery.callbacks 注释的更多相关文章
- jQuery.Callbacks之demo
jQuery.Callbacks是jquery在1.7版本之后加入的,是从1.6版中的_Deferred对象中抽离的,主要用来进行函数队列的add.remove.fire.lock等操作,并提供onc ...
- jQuery回调、递延对象总结(上篇)—— jQuery.Callbacks
前言: 作为参数传递给另一个函数执行的函数我们称为回调函数,那么该回调又是否是异步的呢,何谓异步,如:作为事件处理器,或作为参数传递给 (setTimeout,setInterval)这样的异步函数, ...
- jQuery.Callbacks 源码解读二
一.参数标记 /* * once: 确保回调列表仅只fire一次 * unique: 在执行add操作中,确保回调列表中不存在重复的回调 * stopOnFalse: 当执行回调返回值为false,则 ...
- jQuery源代码学习之四——jQuery.callbacks
自己实现的callbacks模块相较于jquery源代码中的callbacks模块有所简化,表面上看没有考虑firing这个参数,没有对之进行任何处理,即没有考虑在函数执行过程中,再次调用add,re ...
- jQuery.Callbacks之源码解读
在上一篇jQuery.Callbacks之demo主要说了Callbacks对象初始化常见的选项,这一篇主要分析下Callbacks对象的源代码,对给出两个较为繁琐的demo // String to ...
- jQuery回调、递延对象总结(一)jQuery.Callbacks详解
前言: 作为参数传递给另一个函数执行的函数我们称为回调函数,那么该回调又是否是异步的呢,何谓异步,如:作为事件处理器,或作为参数传递给 (setTimeout,setInterval)这样的异步函数, ...
- jQuery: Callbacks
jQuery 中提供了一个Callback的工具类Callbacks,它提供了一个Callback Chain.使用它可以在一个chain上来执行相关操作.它也是jQuery中的ajax, Defer ...
- jquery.Callbacks的实现
前言 本人是一个热爱前端的菜鸟,一直喜欢学习js原生,对于jq这种js库,比较喜欢理解他的实现,虽然自己能力有限,水平很低,但是勉勉强强也算是能够懂一点吧,对于jq源码解读系列,博客园里有很多,推荐大 ...
- jQuery 2.0.3 源码分析 回调对象 - Callbacks
源码API:http://api.jquery.com/jQuery.Callbacks/ jQuery.Callbacks()是在版本1.7中新加入的.它是一个多用途的回调函数列表对象,提供了一种强 ...
随机推荐
- Android服务Service具体解释(作用,生命周期,AIDL)系列文章-为什么须要服务呢?
Android服务Service具体解释(作用,生命周期,AIDL) 近期沉迷于上班,没有时间写博客了.解衣入睡,未眠.随起床写一篇博客压压惊! ##我们android系统为什么须要服务Service ...
- zabbix主机自动发现和监控
在主机较多的时候,配置主机自动发现并加入监控可以代替手动的添加主机,减轻工作量,自动发现由服务端主动发起,Zabbix Server开启发现进程,定时扫描局域网中IP服务器.设备.可以根据需要,在对主 ...
- Node.js 使用http客户端向网站请求数据并保存
app.js代码: // 内置http模块,提供了http服务器和客户端功能 var http=require("http"); // 内置文件处理模块 var fs=requir ...
- #淘宝#复制分享宝贝内容,打开淘宝APP,自己主动弹出宝贝提示信息
场景描写叙述: 淘宝复制连接,分享出去,比方拷贝到QQ好友.微信好友,一个宝贝信息.然后你朋友长按复制你分享它了的这个宝贝.当然打开手机淘宝时.自己主动会跳出宝贝的信息,点击确定能够直接进入宝贝详情 ...
- 斯坦福《机器学习》Lesson4感想--1、Logistic回归中的牛顿方法
在上一篇中提到的Logistic回归是利用最大似然概率的思想和梯度上升算法确定θ,从而确定f(θ).本篇将介绍还有一种求解最大似然概率ℓ(θ)的方法,即牛顿迭代法. 在牛顿迭代法中.如果一个函数是,求 ...
- OSGI中的service依赖关系管理
众所周知.对于高动态高可扩展的应用,OSGI是一个很好的平台.可是.也因此添加了复杂性.开发中对service的依赖变得复杂. 这也是service的关系管理成为OSGI中一个很重要的部分,我们来看看 ...
- 《windows核心编程》 在应用程序中使用虚拟内存
Microsoft Windows 提供了以下三种机制来对内存进行操控: 虚拟内存 最适合用来管理大型对象数组或大型结构数组 内存映射文件 最适合用来管理大型数据流(通常是文件),以及在同一台机器上运 ...
- android端StarIO热敏打印机打印小票
最近在做这个热敏打印机打印小票,开始的时候在网上找资料,发现国内基本没有这方面的资料,国外也很少,在此做个打印小票的记录. 这里只记录一些关键点. 使用StarIOPort.searchPrinter ...
- LINUX find 实用
查找文件find ./ -type f 查找目录find ./ -type d 查找名字为test的文件或目录find ./ -name test 查找名字符合正则表达式的文件,注意前面的‘.*’(查 ...
- Http调试工具-Fiddler使用指引
转自:http://my.oschina.net/u/1388024/blog/186886#OSC_h1_9 目录[-] Fiddler是什么? Fiddler能做什么? 从哪里下载? 安装: 初次 ...